Add project files.
This commit is contained in:
29
libsql/CMakeLists.txt
Normal file
29
libsql/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(libsql CXX)
|
||||
|
||||
# Find source files
|
||||
file(GLOB SOURCES
|
||||
"src/*.cpp"
|
||||
"include/*.h"
|
||||
)
|
||||
|
||||
# Include header files
|
||||
include_directories("include")
|
||||
|
||||
# Create shared library
|
||||
add_library(${PROJECT_NAME} STATIC ${SOURCES})
|
||||
|
||||
# Find dependencies
|
||||
find_package(libmysql REQUIRED)
|
||||
find_package(Boost REQUIRED)
|
||||
|
||||
# Link dependencies if found
|
||||
if (libmysql_FOUND)
|
||||
target_link_libraries (${PROJECT_NAME} ${MYSQL_LIBRARIES})
|
||||
endif (libmysql_FOUND)
|
||||
|
||||
if (Boost_FOUND)
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
target_link_libraries (${PROJECT_NAME} ${Boost_LIBRARIES})
|
||||
endif (Boost_FOUND)
|
210
libsql/include/CAsyncSQL.h
Normal file
210
libsql/include/CAsyncSQL.h
Normal file
@ -0,0 +1,210 @@
|
||||
#ifndef __INC_METIN_II_ASYNCSQL_H__
|
||||
#define __INC_METIN_II_ASYNCSQL_H__
|
||||
|
||||
#include <libthecore/include/stdafx.h>
|
||||
#include <libthecore/include/log.h>
|
||||
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <mysql/mysql.h>
|
||||
#include <mysql/errmsg.h>
|
||||
#include <mysql/mysqld_error.h>
|
||||
|
||||
#include "CSemaphore.h"
|
||||
|
||||
#define QUERY_MAX_LEN 8192
|
||||
|
||||
typedef struct _SQLResult
|
||||
{
|
||||
_SQLResult()
|
||||
: pSQLResult(NULL), uiNumRows(0), uiAffectedRows(0), uiInsertID(0)
|
||||
{
|
||||
}
|
||||
|
||||
~_SQLResult()
|
||||
{
|
||||
if (pSQLResult)
|
||||
{
|
||||
mysql_free_result(pSQLResult);
|
||||
pSQLResult = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
MYSQL_RES * pSQLResult;
|
||||
uint32_t uiNumRows;
|
||||
uint32_t uiAffectedRows;
|
||||
uint32_t uiInsertID;
|
||||
} SQLResult;
|
||||
|
||||
typedef struct _SQLMsg
|
||||
{
|
||||
_SQLMsg() : m_pkSQL(NULL), iID(0), uiResultPos(0), pvUserData(NULL), bReturn(false), uiSQLErrno(0)
|
||||
{
|
||||
}
|
||||
|
||||
~_SQLMsg()
|
||||
{
|
||||
std::vector<SQLResult *>::iterator first = vec_pkResult.begin();
|
||||
std::vector<SQLResult *>::iterator past = vec_pkResult.end();
|
||||
|
||||
while (first != past)
|
||||
delete *(first++);
|
||||
|
||||
vec_pkResult.clear();
|
||||
}
|
||||
|
||||
void Store()
|
||||
{
|
||||
do
|
||||
{
|
||||
SQLResult * pRes = new SQLResult;
|
||||
|
||||
pRes->pSQLResult = mysql_store_result(m_pkSQL);
|
||||
pRes->uiInsertID = mysql_insert_id(m_pkSQL);
|
||||
pRes->uiAffectedRows = mysql_affected_rows(m_pkSQL);
|
||||
|
||||
if (pRes->pSQLResult)
|
||||
{
|
||||
pRes->uiNumRows = mysql_num_rows(pRes->pSQLResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
pRes->uiNumRows = 0;
|
||||
}
|
||||
|
||||
vec_pkResult.push_back(pRes);
|
||||
} while (!mysql_next_result(m_pkSQL));
|
||||
}
|
||||
|
||||
SQLResult * Get()
|
||||
{
|
||||
if (uiResultPos >= vec_pkResult.size())
|
||||
return NULL;
|
||||
|
||||
return vec_pkResult[uiResultPos];
|
||||
}
|
||||
|
||||
bool Next()
|
||||
{
|
||||
if (uiResultPos + 1 >= vec_pkResult.size())
|
||||
return false;
|
||||
|
||||
++uiResultPos;
|
||||
return true;
|
||||
}
|
||||
|
||||
MYSQL * m_pkSQL;
|
||||
int iID;
|
||||
std::string stQuery;
|
||||
|
||||
std::vector<SQLResult *> vec_pkResult; // result <20><><EFBFBD><EFBFBD>
|
||||
unsigned int uiResultPos; // <20><><EFBFBD><EFBFBD> result <20><>ġ
|
||||
|
||||
void * pvUserData;
|
||||
bool bReturn;
|
||||
|
||||
unsigned int uiSQLErrno;
|
||||
} SQLMsg;
|
||||
|
||||
class CAsyncSQL
|
||||
{
|
||||
public:
|
||||
CAsyncSQL();
|
||||
virtual ~CAsyncSQL();
|
||||
|
||||
void Quit();
|
||||
|
||||
bool Setup(const char * c_pszHost, const char * c_pszUser, const char * c_pszPassword, const char * c_pszDB, const char * c_pszLocale,
|
||||
bool bNoThread = false, int iPort = 0);
|
||||
bool Setup(CAsyncSQL * sql, bool bNoThread = false);
|
||||
|
||||
bool Connect();
|
||||
bool IsConnected() { return m_bConnected; }
|
||||
bool QueryLocaleSet();
|
||||
|
||||
void AsyncQuery(const char * c_pszQuery);
|
||||
void ReturnQuery(const char * c_pszQuery, void * pvUserData);
|
||||
SQLMsg * DirectQuery(const char * c_pszQuery);
|
||||
|
||||
DWORD CountQuery();
|
||||
DWORD CountResult();
|
||||
|
||||
void PushResult(SQLMsg * p);
|
||||
bool PopResult(SQLMsg ** pp);
|
||||
|
||||
void ChildLoop();
|
||||
|
||||
MYSQL * GetSQLHandle();
|
||||
|
||||
int CountQueryFinished();
|
||||
void ResetQueryFinished();
|
||||
|
||||
size_t EscapeString(char* dst, size_t dstSize, const char *src, size_t srcSize);
|
||||
|
||||
protected:
|
||||
void Destroy();
|
||||
|
||||
void PushQuery(SQLMsg * p);
|
||||
|
||||
bool PeekQuery(SQLMsg ** pp);
|
||||
bool PopQuery(int iID);
|
||||
|
||||
bool PeekQueryFromCopyQueue(SQLMsg ** pp );
|
||||
INT CopyQuery();
|
||||
bool PopQueryFromCopyQueue();
|
||||
|
||||
public:
|
||||
int GetCopiedQueryCount();
|
||||
void ResetCopiedQueryCount();
|
||||
void AddCopiedQueryCount( int iCopiedQuery );
|
||||
|
||||
//private:
|
||||
protected:
|
||||
MYSQL m_hDB;
|
||||
|
||||
std::string m_stHost;
|
||||
std::string m_stUser;
|
||||
std::string m_stPassword;
|
||||
std::string m_stDB;
|
||||
std::string m_stLocale;
|
||||
|
||||
int m_iMsgCount;
|
||||
int m_aiPipe[2];
|
||||
int m_iPort;
|
||||
|
||||
std::queue<SQLMsg *> m_queue_query;
|
||||
std::queue<SQLMsg *> m_queue_query_copy;
|
||||
//std::map<int, SQLMsg *> m_map_kSQLMsgUnfinished;
|
||||
|
||||
std::queue<SQLMsg *> m_queue_result;
|
||||
|
||||
volatile bool m_bEnd;
|
||||
|
||||
#ifndef __WIN32__
|
||||
pthread_t m_hThread;
|
||||
pthread_mutex_t * m_mtxQuery;
|
||||
pthread_mutex_t * m_mtxResult;
|
||||
#else
|
||||
HANDLE m_hThread;
|
||||
CRITICAL_SECTION* m_mtxQuery;
|
||||
CRITICAL_SECTION* m_mtxResult;
|
||||
#endif
|
||||
|
||||
CSemaphore m_sem;
|
||||
|
||||
int m_iQueryFinished;
|
||||
|
||||
unsigned long m_ulThreadID;
|
||||
bool m_bConnected;
|
||||
int m_iCopiedQuery;
|
||||
};
|
||||
|
||||
class CAsyncSQL2 : public CAsyncSQL
|
||||
{
|
||||
public:
|
||||
void SetLocale ( const std::string & stLocale );
|
||||
};
|
||||
|
||||
#endif
|
22
libsql/include/CSemaphore.h
Normal file
22
libsql/include/CSemaphore.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef __INC_METIN_II_SEMAPHORE_H__
|
||||
#define __INC_METIN_II_SEMAPHORE_H__
|
||||
|
||||
#include <semaphore.h>
|
||||
|
||||
class CSemaphore
|
||||
{
|
||||
private:
|
||||
sem_t * m_hSem;
|
||||
|
||||
|
||||
public:
|
||||
CSemaphore();
|
||||
~CSemaphore();
|
||||
|
||||
int Initialize();
|
||||
void Clear();
|
||||
void Destroy();
|
||||
int Wait();
|
||||
int Release(int count = 1);
|
||||
};
|
||||
#endif
|
41
libsql/include/CStatement.h
Normal file
41
libsql/include/CStatement.h
Normal file
@ -0,0 +1,41 @@
|
||||
#ifndef __INC_METIN_II_LIBSQL_STATEMENT_H__
|
||||
#define __INC_METIN_II_LIBSQL_STATEMENT_H__
|
||||
|
||||
#include "CAsyncSQL.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CStmt
|
||||
{
|
||||
public:
|
||||
CStmt();
|
||||
virtual ~CStmt();
|
||||
|
||||
bool Prepare(CAsyncSQL * sql, const char * c_pszQuery);
|
||||
bool BindParam(enum_field_types type, void * p, int iMaxLen=0);
|
||||
bool BindResult(enum_field_types type, void * p, int iMaxLen=0);
|
||||
int Execute();
|
||||
bool Fetch();
|
||||
|
||||
void Error(const char * c_pszMsg);
|
||||
|
||||
public:
|
||||
int iRows;
|
||||
|
||||
private:
|
||||
void Destroy();
|
||||
|
||||
MYSQL_STMT * m_pkStmt;
|
||||
|
||||
std::string m_stQuery;
|
||||
|
||||
std::vector<MYSQL_BIND> m_vec_param;
|
||||
unsigned int m_uiParamCount;
|
||||
long unsigned int * m_puiParamLen;
|
||||
|
||||
std::vector<MYSQL_BIND> m_vec_result;
|
||||
unsigned int m_uiResultCount;
|
||||
};
|
||||
|
||||
#endif
|
16
libsql/include/Tellwait.h
Normal file
16
libsql/include/Tellwait.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __INC_METIN_II_TELLWAIT_H__
|
||||
#define __INC_METIN_II_TELLWAIT_H__
|
||||
|
||||
#ifndef __WIN32__
|
||||
|
||||
extern void TELL_WAIT();
|
||||
|
||||
extern void WAIT_CHILD();
|
||||
extern void TELL_CHILD(pid_t pid);
|
||||
|
||||
extern void WAIT_PARENT();
|
||||
extern void TELL_PARENT(pid_t pid);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
1
libsql/include/libsql.h
Normal file
1
libsql/include/libsql.h
Normal file
@ -0,0 +1 @@
|
||||
#include "AsyncSQL.h"
|
2
libsql/include/stdafx.h
Normal file
2
libsql/include/stdafx.h
Normal file
@ -0,0 +1,2 @@
|
||||
#include <libthecore/include/stdafx.h>
|
||||
#include "CAsyncSQL.h"
|
716
libsql/src/CAsyncSQL.cpp
Normal file
716
libsql/src/CAsyncSQL.cpp
Normal file
@ -0,0 +1,716 @@
|
||||
#ifndef __WIN32__
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "CAsyncSQL.h"
|
||||
|
||||
// TODO: Consider providing platform-independent mutex class.
|
||||
#ifndef __WIN32__
|
||||
#define MUTEX_LOCK(mtx) pthread_mutex_lock(mtx)
|
||||
#define MUTEX_UNLOCK(mtx) pthread_mutex_unlock(mtx)
|
||||
#else
|
||||
#define MUTEX_LOCK(mtx) ::EnterCriticalSection(mtx)
|
||||
#define MUTEX_UNLOCK(mtx) ::LeaveCriticalSection(mtx)
|
||||
#endif
|
||||
|
||||
CAsyncSQL::CAsyncSQL()
|
||||
: m_stHost(""), m_stUser(""), m_stPassword(""), m_stDB(""), m_stLocale(""),
|
||||
m_iMsgCount(0), m_bEnd(false),
|
||||
#ifndef __WIN32__
|
||||
m_hThread(0),
|
||||
#else
|
||||
m_hThread(INVALID_HANDLE_VALUE),
|
||||
#endif
|
||||
m_mtxQuery(NULL), m_mtxResult(NULL),
|
||||
m_iQueryFinished(0), m_ulThreadID(0), m_bConnected(false), m_iCopiedQuery(0),
|
||||
m_iPort(0)
|
||||
{
|
||||
memset( &m_hDB, 0, sizeof(m_hDB) );
|
||||
|
||||
m_aiPipe[0] = 0;
|
||||
m_aiPipe[1] = 0;
|
||||
}
|
||||
|
||||
CAsyncSQL::~CAsyncSQL()
|
||||
{
|
||||
Quit();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void CAsyncSQL::Destroy()
|
||||
{
|
||||
if (m_hDB.host)
|
||||
{
|
||||
sys_log(0, "AsyncSQL: closing mysql connection.");
|
||||
mysql_close(&m_hDB);
|
||||
m_hDB.host = NULL;
|
||||
}
|
||||
|
||||
if (m_mtxQuery)
|
||||
{
|
||||
#ifndef __WIN32__
|
||||
pthread_mutex_destroy(m_mtxQuery);
|
||||
#else
|
||||
::DeleteCriticalSection(m_mtxQuery);
|
||||
#endif
|
||||
delete m_mtxQuery;
|
||||
m_mtxQuery = NULL;
|
||||
}
|
||||
|
||||
if (m_mtxResult)
|
||||
{
|
||||
#ifndef __WIN32__
|
||||
pthread_mutex_destroy(m_mtxResult);
|
||||
#else
|
||||
::DeleteCriticalSection(m_mtxResult);
|
||||
#endif
|
||||
delete m_mtxResult;
|
||||
m_mtxQuery = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __WIN32__
|
||||
void * AsyncSQLThread(void * arg)
|
||||
#else
|
||||
unsigned int __stdcall AsyncSQLThread(void* arg)
|
||||
#endif
|
||||
{
|
||||
CAsyncSQL * pSQL = ((CAsyncSQL *) arg);
|
||||
|
||||
if (!pSQL->Connect())
|
||||
return NULL;
|
||||
|
||||
pSQL->ChildLoop();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CAsyncSQL::QueryLocaleSet()
|
||||
{
|
||||
if (0 == m_stLocale.length())
|
||||
{
|
||||
sys_err("m_stLocale == 0");
|
||||
return true;
|
||||
}
|
||||
|
||||
else if (m_stLocale == "ascii")
|
||||
{
|
||||
sys_err("m_stLocale == ascii");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mysql_set_character_set(&m_hDB, m_stLocale.c_str()))
|
||||
{
|
||||
sys_err("cannot set locale %s by 'mysql_set_character_set', errno %u %s", m_stLocale.c_str(), mysql_errno(&m_hDB) , mysql_error(&m_hDB));
|
||||
return false;
|
||||
}
|
||||
|
||||
sys_log(0, "\t--mysql_set_character_set(%s)", m_stLocale.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAsyncSQL::Connect()
|
||||
{
|
||||
if (0 == mysql_init(&m_hDB))
|
||||
{
|
||||
fprintf(stderr, "mysql_init failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
//mysql_options(&m_hDB, MYSQL_SET_CHARSET_NAME, m_stLocale.c_str());
|
||||
if (!m_stLocale.empty())
|
||||
{
|
||||
//mysql_options(&m_hDB, MYSQL_SET_CHARSET_DIR , " /usr/local/share/mysql/charsets/");
|
||||
//mysql_options(&m_hDB, MYSQL_SET_CHARSET_DIR , "/usr/local/share/mysql/charsets");
|
||||
//mysql_options(&m_hDB, MYSQL_SET_CHARSET_DIR , "/usr/local/share/mysql");
|
||||
if (mysql_options(&m_hDB, MYSQL_SET_CHARSET_NAME, m_stLocale.c_str()) != 0)
|
||||
{
|
||||
fprintf(stderr, "mysql_option failed : MYSQL_SET_CHARSET_NAME %s ", mysql_error(&m_hDB));
|
||||
}
|
||||
}
|
||||
|
||||
if (!mysql_real_connect(&m_hDB, m_stHost.c_str(), m_stUser.c_str(), m_stPassword.c_str(), m_stDB.c_str(), m_iPort, NULL, CLIENT_MULTI_STATEMENTS))
|
||||
{
|
||||
fprintf(stderr, "mysql_real_connect: %s\n", mysql_error(&m_hDB));
|
||||
return false;
|
||||
}
|
||||
|
||||
bool reconnect = true;
|
||||
|
||||
if (0 != mysql_options(&m_hDB, MYSQL_OPT_RECONNECT, &reconnect))
|
||||
fprintf(stderr, "mysql_option: %s\n", mysql_error(&m_hDB));
|
||||
|
||||
fprintf(stdout, "AsyncSQL: connected to %s (reconnect %d)\n", m_stHost.c_str(), m_hDB.reconnect);
|
||||
|
||||
// db cache<68><65> common db<64><62> LOCALE <20><><EFBFBD>̺<EFBFBD><CCBA><EFBFBD><EFBFBD><EFBFBD> locale<6C><65> <20>˾ƿ<CBBE><C6BF><EFBFBD>, <20><><EFBFBD><EFBFBD> character set<65><74> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> Connection<6F><6E> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> locale<6C><65> <20><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> character set<65><74> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>ұ<EFBFBD><D2B1>ϰ<EFBFBD>,
|
||||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> character set<65><74> euckr<6B><72> <20><><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD> <20>Ǿ<EFBFBD><C7BE>־<EFBFBD> <20><> <20>κ<EFBFBD><CEBA><EFBFBD> <20>ּ<EFBFBD>ó<EFBFBD><C3B3> <20>Ͽ<EFBFBD><CFBF><EFBFBD>.
|
||||
// (<28>Ʒ<EFBFBD> <20>ּ<EFBFBD><D6BC><EFBFBD> Ǯ<><C7AE> mysql<71><6C> euckr<6B><72> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>ִ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.)
|
||||
//while (!QueryLocaleSet());
|
||||
m_ulThreadID = mysql_thread_id(&m_hDB);
|
||||
|
||||
m_bConnected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAsyncSQL::Setup(CAsyncSQL * sql, bool bNoThread)
|
||||
{
|
||||
return Setup(sql->m_stHost.c_str(),
|
||||
sql->m_stUser.c_str(),
|
||||
sql->m_stPassword.c_str(),
|
||||
sql->m_stDB.c_str(),
|
||||
sql->m_stLocale.c_str(),
|
||||
bNoThread,
|
||||
sql->m_iPort);
|
||||
}
|
||||
|
||||
bool CAsyncSQL::Setup(const char * c_pszHost, const char * c_pszUser, const char * c_pszPassword, const char * c_pszDB, const char * c_pszLocale, bool bNoThread, int iPort)
|
||||
{
|
||||
m_stHost = c_pszHost;
|
||||
m_stUser = c_pszUser;
|
||||
m_stPassword = c_pszPassword;
|
||||
m_stDB = c_pszDB;
|
||||
m_iPort = iPort;
|
||||
|
||||
if (c_pszLocale)
|
||||
{
|
||||
m_stLocale = c_pszLocale;
|
||||
sys_log(0, "AsyncSQL: locale %s", m_stLocale.c_str());
|
||||
}
|
||||
|
||||
if (!bNoThread)
|
||||
{
|
||||
/*
|
||||
if (!mysql_thread_safe())//
|
||||
{
|
||||
fprintf(stderr, "FATAL ERROR!! mysql client library was not compiled with thread safety\n");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
#ifndef __WIN32__
|
||||
m_mtxQuery = new pthread_mutex_t;
|
||||
m_mtxResult = new pthread_mutex_t;
|
||||
|
||||
if (0 != pthread_mutex_init(m_mtxQuery, NULL))
|
||||
{
|
||||
perror("pthread_mutex_init");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (0 != pthread_mutex_init(m_mtxResult, NULL))
|
||||
{
|
||||
perror("pthread_mutex_init");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
pthread_create(&m_hThread, NULL, AsyncSQLThread, this);
|
||||
#else
|
||||
m_mtxQuery = new CRITICAL_SECTION;
|
||||
m_mtxResult = new CRITICAL_SECTION;
|
||||
|
||||
::InitializeCriticalSection(m_mtxQuery);
|
||||
::InitializeCriticalSection(m_mtxResult);
|
||||
|
||||
m_hThread = (HANDLE)::_beginthreadex(NULL, 0, AsyncSQLThread, this, 0, NULL);
|
||||
if (m_hThread == INVALID_HANDLE_VALUE) {
|
||||
perror("CAsyncSQL::Setup");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return Connect();
|
||||
}
|
||||
|
||||
void CAsyncSQL::Quit()
|
||||
{
|
||||
m_bEnd = true;
|
||||
m_sem.Release();
|
||||
|
||||
#ifndef __WIN32__
|
||||
if (m_hThread)
|
||||
{
|
||||
pthread_join(m_hThread, NULL);
|
||||
m_hThread = NULL;
|
||||
}
|
||||
#else
|
||||
if (m_hThread != INVALID_HANDLE_VALUE) {
|
||||
::WaitForSingleObject(m_hThread, INFINITE);
|
||||
m_hThread = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
SQLMsg * CAsyncSQL::DirectQuery(const char * c_pszQuery)
|
||||
{
|
||||
if (m_ulThreadID != mysql_thread_id(&m_hDB))
|
||||
{
|
||||
sys_err("MySQL connection was reconnected. querying locale set");
|
||||
while (!QueryLocaleSet());
|
||||
m_ulThreadID = mysql_thread_id(&m_hDB);
|
||||
}
|
||||
|
||||
SQLMsg * p = new SQLMsg;
|
||||
|
||||
p->m_pkSQL = &m_hDB;
|
||||
p->iID = ++m_iMsgCount;
|
||||
p->stQuery = c_pszQuery;
|
||||
|
||||
if (mysql_real_query(&m_hDB, p->stQuery.c_str(), p->stQuery.length()))
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
snprintf(buf, sizeof(buf),
|
||||
"AsyncSQL::DirectQuery : mysql_query error: %s\nquery: %s",
|
||||
mysql_error(&m_hDB), p->stQuery.c_str());
|
||||
|
||||
sys_err(buf);
|
||||
p->uiSQLErrno = mysql_errno(&m_hDB);
|
||||
}
|
||||
|
||||
p->Store();
|
||||
return p;
|
||||
}
|
||||
|
||||
void CAsyncSQL::AsyncQuery(const char * c_pszQuery)
|
||||
{
|
||||
SQLMsg * p = new SQLMsg;
|
||||
|
||||
p->m_pkSQL = &m_hDB;
|
||||
p->iID = ++m_iMsgCount;
|
||||
p->stQuery = c_pszQuery;
|
||||
|
||||
PushQuery(p);
|
||||
}
|
||||
|
||||
void CAsyncSQL::ReturnQuery(const char * c_pszQuery, void * pvUserData)
|
||||
{
|
||||
SQLMsg * p = new SQLMsg;
|
||||
|
||||
p->m_pkSQL = &m_hDB;
|
||||
p->iID = ++m_iMsgCount;
|
||||
p->stQuery = c_pszQuery;
|
||||
p->bReturn = true;
|
||||
p->pvUserData = pvUserData;
|
||||
|
||||
PushQuery(p);
|
||||
}
|
||||
|
||||
void CAsyncSQL::PushResult(SQLMsg * p)
|
||||
{
|
||||
MUTEX_LOCK(m_mtxResult);
|
||||
|
||||
m_queue_result.push(p);
|
||||
|
||||
MUTEX_UNLOCK(m_mtxResult);
|
||||
}
|
||||
|
||||
bool CAsyncSQL::PopResult(SQLMsg ** pp)
|
||||
{
|
||||
MUTEX_LOCK(m_mtxResult);
|
||||
|
||||
if (m_queue_result.empty())
|
||||
{
|
||||
MUTEX_UNLOCK(m_mtxResult);
|
||||
return false;
|
||||
}
|
||||
|
||||
*pp = m_queue_result.front();
|
||||
m_queue_result.pop();
|
||||
MUTEX_UNLOCK(m_mtxResult);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CAsyncSQL::PushQuery(SQLMsg * p)
|
||||
{
|
||||
MUTEX_LOCK(m_mtxQuery);
|
||||
|
||||
m_queue_query.push(p);
|
||||
//m_map_kSQLMsgUnfinished.insert(std::make_pair(p->iID, p));
|
||||
|
||||
m_sem.Release();
|
||||
|
||||
MUTEX_UNLOCK(m_mtxQuery);
|
||||
}
|
||||
|
||||
bool CAsyncSQL::PeekQuery(SQLMsg ** pp)
|
||||
{
|
||||
MUTEX_LOCK(m_mtxQuery);
|
||||
|
||||
if (m_queue_query.empty())
|
||||
{
|
||||
MUTEX_UNLOCK(m_mtxQuery);
|
||||
return false;
|
||||
}
|
||||
|
||||
*pp = m_queue_query.front();
|
||||
MUTEX_UNLOCK(m_mtxQuery);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAsyncSQL::PopQuery(int iID)
|
||||
{
|
||||
MUTEX_LOCK(m_mtxQuery);
|
||||
|
||||
if (m_queue_query.empty())
|
||||
{
|
||||
MUTEX_UNLOCK(m_mtxQuery);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_queue_query.pop();
|
||||
//m_map_kSQLMsgUnfinished.erase(iID);
|
||||
|
||||
MUTEX_UNLOCK(m_mtxQuery);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAsyncSQL::PeekQueryFromCopyQueue(SQLMsg ** pp)
|
||||
{
|
||||
if (m_queue_query_copy.empty())
|
||||
return false;
|
||||
|
||||
*pp = m_queue_query_copy.front();
|
||||
return true;
|
||||
}
|
||||
|
||||
int CAsyncSQL::CopyQuery()
|
||||
{
|
||||
MUTEX_LOCK(m_mtxQuery);
|
||||
|
||||
if (m_queue_query.empty())
|
||||
{
|
||||
MUTEX_UNLOCK(m_mtxQuery);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (!m_queue_query.empty())
|
||||
{
|
||||
SQLMsg * p = m_queue_query.front();
|
||||
m_queue_query_copy.push(p);
|
||||
m_queue_query.pop();
|
||||
}
|
||||
|
||||
//m_map_kSQLMsgUnfinished.erase(iID);
|
||||
|
||||
int count = m_queue_query_copy.size();
|
||||
|
||||
MUTEX_UNLOCK(m_mtxQuery);
|
||||
return count;
|
||||
}
|
||||
|
||||
bool CAsyncSQL::PopQueryFromCopyQueue()
|
||||
{
|
||||
if (m_queue_query_copy.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_queue_query_copy.pop();
|
||||
//m_map_kSQLMsgUnfinished.erase(iID);
|
||||
|
||||
return true;
|
||||
}
|
||||
int CAsyncSQL::GetCopiedQueryCount()
|
||||
{
|
||||
return m_iCopiedQuery;
|
||||
}
|
||||
void CAsyncSQL::ResetCopiedQueryCount()
|
||||
{
|
||||
m_iCopiedQuery = 0;
|
||||
}
|
||||
|
||||
void CAsyncSQL::AddCopiedQueryCount(int iCopiedQuery)
|
||||
{
|
||||
m_iCopiedQuery += iCopiedQuery;
|
||||
}
|
||||
|
||||
|
||||
|
||||
DWORD CAsyncSQL::CountQuery()
|
||||
{
|
||||
return m_queue_query.size();
|
||||
}
|
||||
|
||||
DWORD CAsyncSQL::CountResult()
|
||||
{
|
||||
return m_queue_result.size();
|
||||
}
|
||||
|
||||
void __timediff(struct timeval *a, struct timeval *b, struct timeval *rslt)
|
||||
{
|
||||
if (a->tv_sec < b->tv_sec)
|
||||
rslt->tv_sec = rslt->tv_usec = 0;
|
||||
else if (a->tv_sec == b->tv_sec)
|
||||
{
|
||||
if (a->tv_usec < b->tv_usec)
|
||||
rslt->tv_sec = rslt->tv_usec = 0;
|
||||
else
|
||||
{
|
||||
rslt->tv_sec = 0;
|
||||
rslt->tv_usec = a->tv_usec - b->tv_usec;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* a->tv_sec > b->tv_sec */
|
||||
rslt->tv_sec = a->tv_sec - b->tv_sec;
|
||||
|
||||
if (a->tv_usec < b->tv_usec)
|
||||
{
|
||||
rslt->tv_usec = a->tv_usec + 1000000 - b->tv_usec;
|
||||
rslt->tv_sec--;
|
||||
} else
|
||||
rslt->tv_usec = a->tv_usec - b->tv_usec;
|
||||
}
|
||||
}
|
||||
|
||||
class cProfiler
|
||||
{
|
||||
public:
|
||||
cProfiler()
|
||||
{
|
||||
m_nInterval = 0 ;
|
||||
|
||||
memset( &prev, 0, sizeof(prev) );
|
||||
memset( &now, 0, sizeof(now) );
|
||||
memset( &interval, 0, sizeof(interval) );
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
cProfiler(int nInterval = 100000)
|
||||
{
|
||||
m_nInterval = nInterval;
|
||||
|
||||
memset( &prev, 0, sizeof(prev) );
|
||||
memset( &now, 0, sizeof(now) );
|
||||
memset( &interval, 0, sizeof(interval) );
|
||||
|
||||
Start();
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
gettimeofday (&prev , (struct timezone *) 0);
|
||||
}
|
||||
|
||||
void Stop()
|
||||
{
|
||||
gettimeofday(&now, (struct timezone*) 0);
|
||||
__timediff(&now, &prev, &interval);
|
||||
}
|
||||
|
||||
bool IsOk()
|
||||
{
|
||||
if (interval.tv_sec > (m_nInterval / 1000000))
|
||||
return false;
|
||||
|
||||
if (interval.tv_usec > m_nInterval)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct timeval * GetResult() { return &interval; }
|
||||
long GetResultSec() { return interval.tv_sec; }
|
||||
long GetResultUSec() { return interval.tv_usec; }
|
||||
|
||||
private:
|
||||
int m_nInterval;
|
||||
struct timeval prev;
|
||||
struct timeval now;
|
||||
struct timeval interval;
|
||||
};
|
||||
|
||||
void CAsyncSQL::ChildLoop()
|
||||
{
|
||||
cProfiler profiler(500000); // 0.5<EFBFBD><EFBFBD>
|
||||
|
||||
while (!m_bEnd)
|
||||
{
|
||||
m_sem.Wait();
|
||||
|
||||
int count = CopyQuery();
|
||||
|
||||
if (count <= 0)
|
||||
continue;
|
||||
|
||||
AddCopiedQueryCount(count);
|
||||
|
||||
SQLMsg * p;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
//<2F>ð<EFBFBD> üũ <20><><EFBFBD><EFBFBD>
|
||||
profiler.Start();
|
||||
|
||||
if (!PeekQueryFromCopyQueue(&p))
|
||||
continue;
|
||||
|
||||
if (m_ulThreadID != mysql_thread_id(&m_hDB))
|
||||
{
|
||||
sys_err("MySQL connection was reconnected. querying locale set");
|
||||
while (!QueryLocaleSet());
|
||||
m_ulThreadID = mysql_thread_id(&m_hDB);
|
||||
}
|
||||
|
||||
if (mysql_real_query(&m_hDB, p->stQuery.c_str(), p->stQuery.length()))
|
||||
{
|
||||
p->uiSQLErrno = mysql_errno(&m_hDB);
|
||||
|
||||
sys_err("AsyncSQL: query failed: %s (query: %s errno: %d)",
|
||||
mysql_error(&m_hDB), p->stQuery.c_str(), p->uiSQLErrno);
|
||||
|
||||
switch (p->uiSQLErrno)
|
||||
{
|
||||
case CR_SOCKET_CREATE_ERROR:
|
||||
case CR_CONNECTION_ERROR:
|
||||
case CR_IPSOCK_ERROR:
|
||||
case CR_UNKNOWN_HOST:
|
||||
case CR_SERVER_GONE_ERROR:
|
||||
case CR_CONN_HOST_ERROR:
|
||||
case ER_NOT_KEYFILE:
|
||||
case ER_CRASHED_ON_USAGE:
|
||||
case ER_CANT_OPEN_FILE:
|
||||
case ER_HOST_NOT_PRIVILEGED:
|
||||
case ER_HOST_IS_BLOCKED:
|
||||
case ER_PASSWORD_NOT_ALLOWED:
|
||||
case ER_PASSWORD_NO_MATCH:
|
||||
case ER_CANT_CREATE_THREAD:
|
||||
case ER_INVALID_USE_OF_NULL:
|
||||
m_sem.Release();
|
||||
sys_err("AsyncSQL: retrying");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
profiler.Stop();
|
||||
|
||||
// 0.5<EFBFBD><EFBFBD> <20>̻<EFBFBD> <20>ɷ<EFBFBD><C9B7><EFBFBD><EFBFBD><EFBFBD> <20>α<CEB1> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
if (!profiler.IsOk())
|
||||
sys_log(0, "[QUERY : LONG INTERVAL(OverSec %ld.%ld)] : %s",
|
||||
profiler.GetResultSec(), profiler.GetResultUSec(), p->stQuery.c_str());
|
||||
|
||||
PopQueryFromCopyQueue();
|
||||
|
||||
if (p->bReturn)
|
||||
{
|
||||
p->Store();
|
||||
PushResult(p);
|
||||
}
|
||||
else
|
||||
delete p;
|
||||
|
||||
++m_iQueryFinished;
|
||||
}
|
||||
}
|
||||
|
||||
SQLMsg * p;
|
||||
|
||||
while (PeekQuery(&p))
|
||||
{
|
||||
if (m_ulThreadID != mysql_thread_id(&m_hDB))
|
||||
{
|
||||
sys_err("MySQL connection was reconnected. querying locale set");
|
||||
while (!QueryLocaleSet());
|
||||
m_ulThreadID = mysql_thread_id(&m_hDB);
|
||||
}
|
||||
|
||||
if (mysql_real_query(&m_hDB, p->stQuery.c_str(), p->stQuery.length()))
|
||||
{
|
||||
p->uiSQLErrno = mysql_errno(&m_hDB);
|
||||
|
||||
sys_err("AsyncSQL::ChildLoop : mysql_query error: %s:\nquery: %s",
|
||||
mysql_error(&m_hDB), p->stQuery.c_str());
|
||||
|
||||
switch (p->uiSQLErrno)
|
||||
{
|
||||
case CR_SOCKET_CREATE_ERROR:
|
||||
case CR_CONNECTION_ERROR:
|
||||
case CR_IPSOCK_ERROR:
|
||||
case CR_UNKNOWN_HOST:
|
||||
case CR_SERVER_GONE_ERROR:
|
||||
case CR_CONN_HOST_ERROR:
|
||||
case ER_NOT_KEYFILE:
|
||||
case ER_CRASHED_ON_USAGE:
|
||||
case ER_CANT_OPEN_FILE:
|
||||
case ER_HOST_NOT_PRIVILEGED:
|
||||
case ER_HOST_IS_BLOCKED:
|
||||
case ER_PASSWORD_NOT_ALLOWED:
|
||||
case ER_PASSWORD_NO_MATCH:
|
||||
case ER_CANT_CREATE_THREAD:
|
||||
case ER_INVALID_USE_OF_NULL:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sys_log(0, "QUERY_FLUSH: %s", p->stQuery.c_str());
|
||||
|
||||
PopQuery(p->iID);
|
||||
|
||||
if (p->bReturn)
|
||||
{
|
||||
p->Store();
|
||||
PushResult(p);
|
||||
}
|
||||
else
|
||||
delete p;
|
||||
|
||||
++m_iQueryFinished;
|
||||
}
|
||||
}
|
||||
|
||||
int CAsyncSQL::CountQueryFinished()
|
||||
{
|
||||
return m_iQueryFinished;
|
||||
}
|
||||
|
||||
void CAsyncSQL::ResetQueryFinished()
|
||||
{
|
||||
m_iQueryFinished = 0;
|
||||
}
|
||||
|
||||
MYSQL * CAsyncSQL::GetSQLHandle()
|
||||
{
|
||||
return &m_hDB;
|
||||
}
|
||||
|
||||
size_t CAsyncSQL::EscapeString(char* dst, size_t dstSize, const char *src, size_t srcSize)
|
||||
{
|
||||
if (0 == srcSize)
|
||||
{
|
||||
memset(dst, 0, dstSize);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (0 == dstSize)
|
||||
return 0;
|
||||
|
||||
if (dstSize < srcSize * 2 + 1)
|
||||
{
|
||||
// \0<><30> <20>Ⱥپ<C8BA><D9BE><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> 256 <20><><EFBFBD><EFBFBD>Ʈ<EFBFBD><C6AE> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD> <20>α<CEB1> <20><><EFBFBD><EFBFBD>
|
||||
char tmp[256];
|
||||
size_t tmpLen = sizeof(tmp) > srcSize ? srcSize : sizeof(tmp); // <20><> <20>߿<EFBFBD> <20><><EFBFBD><EFBFBD> ũ<><C5A9>
|
||||
strncpy(tmp, src, tmpLen);
|
||||
|
||||
sys_err("FATAL ERROR!! not enough buffer size (dstSize %u srcSize %u src%s: %s)",
|
||||
dstSize, srcSize, tmpLen != srcSize ? "(trimmed to 255 characters)" : "", tmp);
|
||||
|
||||
dst[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mysql_real_escape_string(GetSQLHandle(), dst, src, srcSize);
|
||||
}
|
||||
|
||||
void CAsyncSQL2::SetLocale(const std::string & stLocale)
|
||||
{
|
||||
m_stLocale = stLocale;
|
||||
QueryLocaleSet();
|
||||
}
|
||||
|
142
libsql/src/CSemaphore.cpp
Normal file
142
libsql/src/CSemaphore.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
#include "stdafx.h"
|
||||
#include "CSemaphore.h"
|
||||
|
||||
#ifndef __WIN32__
|
||||
|
||||
CSemaphore::CSemaphore() : m_hSem(NULL)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
CSemaphore::~CSemaphore()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
int CSemaphore::Initialize()
|
||||
{
|
||||
Clear();
|
||||
|
||||
m_hSem = new sem_t;
|
||||
|
||||
if (sem_init(m_hSem, 0, 0) == -1)
|
||||
{
|
||||
perror("sem_init");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSemaphore::Destroy()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void CSemaphore::Clear()
|
||||
{
|
||||
if (m_hSem)
|
||||
{
|
||||
sem_destroy(m_hSem);
|
||||
delete m_hSem;
|
||||
}
|
||||
|
||||
m_hSem = NULL;
|
||||
}
|
||||
|
||||
int CSemaphore::Wait()
|
||||
{
|
||||
if (!m_hSem)
|
||||
return true;
|
||||
|
||||
int re = sem_wait(m_hSem);
|
||||
|
||||
if (re == -1)
|
||||
{
|
||||
if (errno == EINTR)
|
||||
return Wait();
|
||||
|
||||
perror("sem_wait");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CSemaphore::Release(int count)
|
||||
{
|
||||
if (!m_hSem)
|
||||
return false;
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
sem_post(m_hSem);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
CSemaphore::CSemaphore() : m_hSem(NULL)
|
||||
{
|
||||
Initialize();
|
||||
}
|
||||
|
||||
CSemaphore::~CSemaphore()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
int CSemaphore::Initialize()
|
||||
{
|
||||
Clear();
|
||||
|
||||
m_hSem = ::CreateSemaphore(NULL, 0, 32, NULL);
|
||||
|
||||
if (m_hSem == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CSemaphore::Destroy()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void CSemaphore::Clear()
|
||||
{
|
||||
if (m_hSem == NULL) {
|
||||
return;
|
||||
}
|
||||
::CloseHandle(m_hSem);
|
||||
m_hSem = NULL;
|
||||
}
|
||||
|
||||
int CSemaphore::Wait()
|
||||
{
|
||||
if (!m_hSem)
|
||||
return true;
|
||||
|
||||
DWORD dwWaitResult = ::WaitForSingleObject(m_hSem, INFINITE);
|
||||
|
||||
switch (dwWaitResult) {
|
||||
case WAIT_OBJECT_0:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int CSemaphore::Release(int count)
|
||||
{
|
||||
if (!m_hSem)
|
||||
return false;
|
||||
|
||||
::ReleaseSemaphore(m_hSem, count, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
159
libsql/src/CStatement.cpp
Normal file
159
libsql/src/CStatement.cpp
Normal file
@ -0,0 +1,159 @@
|
||||
#include "CStatement.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
CStmt::CStmt()
|
||||
{
|
||||
m_pkStmt = NULL;
|
||||
m_uiParamCount = 0;
|
||||
m_uiResultCount = 0;
|
||||
iRows = 0;
|
||||
m_puiParamLen = NULL;
|
||||
}
|
||||
|
||||
CStmt::~CStmt()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void CStmt::Destroy()
|
||||
{
|
||||
if (m_pkStmt)
|
||||
{
|
||||
mysql_stmt_close(m_pkStmt);
|
||||
m_pkStmt = NULL;
|
||||
}
|
||||
|
||||
if (m_puiParamLen)
|
||||
{
|
||||
free(m_puiParamLen);
|
||||
m_puiParamLen = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CStmt::Error(const char * c_pszMsg)
|
||||
{
|
||||
sys_log(0, "SYSERR: %s: [%d] %s", c_pszMsg, mysql_stmt_errno(m_pkStmt), mysql_stmt_error(m_pkStmt));
|
||||
}
|
||||
|
||||
bool CStmt::Prepare(CAsyncSQL * sql, const char * c_pszQuery)
|
||||
{
|
||||
m_pkStmt = mysql_stmt_init(sql->GetSQLHandle());
|
||||
m_stQuery = c_pszQuery;
|
||||
|
||||
if (mysql_stmt_prepare(m_pkStmt, m_stQuery.c_str(), m_stQuery.length()))
|
||||
{
|
||||
Error("mysql_stmt_prepare");
|
||||
return false;
|
||||
}
|
||||
|
||||
int iParamCount = 0;
|
||||
|
||||
for (unsigned int i = 0; i < m_stQuery.length(); ++i)
|
||||
if (c_pszQuery[i] == '?')
|
||||
++iParamCount;
|
||||
|
||||
if (iParamCount)
|
||||
{
|
||||
m_vec_param.resize(iParamCount);
|
||||
memset(&m_vec_param[0], 0, sizeof(MYSQL_BIND) * iParamCount);
|
||||
|
||||
m_puiParamLen = (long unsigned int *) calloc(iParamCount, sizeof(long unsigned int));
|
||||
}
|
||||
|
||||
m_vec_result.resize(48);
|
||||
memset(&m_vec_result[0], 0, sizeof(MYSQL_BIND) * 48);
|
||||
|
||||
if (mysql_stmt_bind_result(m_pkStmt, &m_vec_result[0]))
|
||||
{
|
||||
Error("mysql_stmt_bind_result");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CStmt::BindParam(enum_field_types type, void * p, int iMaxLen)
|
||||
{
|
||||
if (m_uiParamCount >= m_vec_param.size())
|
||||
{
|
||||
sys_err("too many parameter in query: %s", m_stQuery.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
MYSQL_BIND * bind = &m_vec_param[m_uiParamCount];
|
||||
|
||||
bind->buffer_type = type;
|
||||
bind->buffer = (void *) p;
|
||||
bind->buffer_length = iMaxLen;
|
||||
bind->length = m_puiParamLen + m_uiParamCount;
|
||||
|
||||
if (++m_uiParamCount == m_vec_param.size())
|
||||
{
|
||||
if (mysql_stmt_bind_param(m_pkStmt, &m_vec_param[0]))
|
||||
{
|
||||
Error("mysql_stmt_bind_param");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CStmt::BindResult(enum_field_types type, void * p, int iMaxLen)
|
||||
{
|
||||
if (m_uiResultCount >= m_vec_result.size())
|
||||
{
|
||||
sys_err("too many result in query: %s", m_stQuery.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
MYSQL_BIND * bind = &m_vec_result[m_uiResultCount++];
|
||||
|
||||
bind->buffer_type = type;
|
||||
bind->buffer = (void *) p;
|
||||
bind->buffer_length = iMaxLen;
|
||||
return true;
|
||||
}
|
||||
|
||||
int CStmt::Execute()
|
||||
{
|
||||
if (m_uiParamCount != m_vec_param.size())
|
||||
{
|
||||
sys_log(0, "Parameter not enough %d, expected %d query: %s", m_uiParamCount, m_vec_param.size(), m_stQuery.c_str());
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < m_uiParamCount; ++i)
|
||||
{
|
||||
MYSQL_BIND * bind = &m_vec_param[i];
|
||||
|
||||
if (bind->buffer_type == MYSQL_TYPE_STRING)
|
||||
{
|
||||
*(m_puiParamLen + i) = strlen((const char *) bind->buffer);
|
||||
sys_log(0, "param %d len %d buf %s", i, *m_puiParamLen, (const char *) bind->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (mysql_stmt_execute(m_pkStmt))
|
||||
{
|
||||
Error("mysql_stmt_execute");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mysql_stmt_store_result(m_pkStmt))
|
||||
{
|
||||
Error("mysql_store_result");
|
||||
return 0;
|
||||
}
|
||||
|
||||
iRows = mysql_stmt_num_rows(m_pkStmt);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CStmt::Fetch()
|
||||
{
|
||||
return !mysql_stmt_fetch(m_pkStmt);
|
||||
}
|
||||
|
87
libsql/src/Tellwait.cpp
Normal file
87
libsql/src/Tellwait.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#ifndef __WIN32__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
|
||||
static volatile sig_atomic_t sigflag;
|
||||
|
||||
/* set nonzero by signal handler */
|
||||
static sigset_t newmask, oldmask, zeromask;
|
||||
|
||||
static void sig_usr(int signo) /* one signal handler for SIGUSR1 and SIGUSR2 */
|
||||
{
|
||||
sigflag = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
void TELL_WAIT()
|
||||
{
|
||||
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
|
||||
{
|
||||
fprintf(stderr, "signal(SIGINT) error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (signal(SIGUSR2, sig_usr) == SIG_ERR)
|
||||
{
|
||||
fprintf(stderr, "signal(SIGQUIT) error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sigemptyset(&zeromask);
|
||||
|
||||
sigemptyset(&newmask);
|
||||
sigaddset(&newmask, SIGUSR1);
|
||||
sigaddset(&newmask, SIGUSR2);
|
||||
|
||||
/* block SIGUSR1 and SIGUSR2, and save current signal mask */
|
||||
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
|
||||
{
|
||||
fprintf(stderr, "SIG_BLOCK error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void TELL_PARENT(pid_t pid)
|
||||
{
|
||||
kill(pid, SIGUSR2); /* tell parent we're done */
|
||||
}
|
||||
|
||||
void WAIT_PARENT(void)
|
||||
{
|
||||
while (sigflag == 0)
|
||||
sigsuspend(&zeromask); /* and wait for parent */
|
||||
|
||||
sigflag = 0;
|
||||
|
||||
/* reset signal mask to original value */
|
||||
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
|
||||
{
|
||||
fprintf(stderr, "SIG_SETMASK error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void TELL_CHILD(pid_t pid)
|
||||
{
|
||||
kill(pid, SIGUSR1); /* tell child we're done */
|
||||
}
|
||||
|
||||
void WAIT_CHILD(void)
|
||||
{
|
||||
while (sigflag == 0)
|
||||
sigsuspend(&zeromask); /* and wait for child */
|
||||
|
||||
sigflag = 0;
|
||||
|
||||
/* reset signal mask to original value */
|
||||
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
|
||||
{
|
||||
fprintf(stderr, "SIG_SETMASK error\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user