mirror of https://github.com/GOSTSec/poolserver
Intel
12 years ago
31 changed files with 887 additions and 43 deletions
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
#include "ServerDatabaseEnv.h" |
||||
|
||||
ServerDatabaseWorkerPoolMySQL sDatabase; |
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
#ifndef SERVER_DATABASE_ENV_H_ |
||||
#define SERVER_DATABASE_ENV_H_ |
||||
|
||||
#include "DatabaseEnv.h" |
||||
|
||||
class ServerDatabaseWorkerPoolMySQL : public DatabaseWorkerPoolMySQL |
||||
{ |
||||
}; |
||||
|
||||
extern ServerDatabaseWorkerPoolMySQL sDatabase; |
||||
|
||||
#endif |
@ -1,33 +1,30 @@
@@ -1,33 +1,30 @@
|
||||
#ifndef DATABASE_H_ |
||||
#define DATABASE_H_ |
||||
|
||||
class Database; |
||||
class ResultSet; |
||||
class Fields; |
||||
class PreparedStatement; |
||||
|
||||
enum PreparedStatementEnum |
||||
{ |
||||
STMT_INSERT_SHARE = 1, |
||||
}; |
||||
#include "QueryResult.h" |
||||
#include "PreparedStatement.h" |
||||
#include "DatabaseCallback.h" |
||||
#include <boost/thread.hpp> |
||||
|
||||
class Database |
||||
{ |
||||
public: |
||||
|
||||
// Ping!
|
||||
virtual Ping(); |
||||
|
||||
// Queries
|
||||
virtual void Execute(const char* query); |
||||
virtual void Execute(PreparedStatement* stmt); |
||||
virtual ResultSet* Query(const char* query); |
||||
virtual ResultSet* Query(PreparedStatement* stmt); |
||||
virtual bool Execute(const char* query) = 0; |
||||
virtual ResultSet* Query(const char* query) = 0; |
||||
|
||||
// Prepared Statements
|
||||
virtual PreparedStatement* GetPreparedStatement(PreparedStatementEnum smtid); |
||||
// Stmt
|
||||
virtual bool Execute(PreparedStatement* stmt) = 0; |
||||
virtual ResultSet* Query(PreparedStatement* stmt) = 0; |
||||
|
||||
// Async
|
||||
virtual bool ExecuteAsync(const char* query) = 0; |
||||
virtual bool ExecuteAsync(PreparedStatement* stmt) = 0; |
||||
virtual bool QueryAsync(DatabaseCallback callback, const char* query) = 0; |
||||
virtual bool QueryAsync(DatabaseCallback callback, PreparedStatement* stmt) = 0; |
||||
|
||||
// Prepared Statements
|
||||
virtual PreparedStatement* GetPreparedStatement(uint32_t index) = 0; |
||||
}; |
||||
|
||||
#endif |
||||
|
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
#ifndef DATABASE_CALLBACK_H_ |
||||
#define DATABASE_CALLBACK_H_ |
||||
|
||||
#include "QueryResult.h" |
||||
|
||||
#include <boost/function.hpp> |
||||
|
||||
typedef boost::function<void(ResultSet*)> DatabaseCallback; |
||||
|
||||
#endif |
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
#ifndef DATABASE_ENV_H_ |
||||
#define DATABASE_ENV_H_ |
||||
|
||||
#include "Database.h" |
||||
|
||||
#ifdef WITH_MYSQL |
||||
#include "MySQL/DatabaseEnvMySQL.h" |
||||
#endif |
||||
|
||||
#endif |
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
#ifndef FIELD_H_ |
||||
#define FIELD_H_ |
||||
|
||||
class Field |
||||
{ |
||||
public: |
||||
//template<class T>
|
||||
//virtual Get();
|
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,149 @@
@@ -0,0 +1,149 @@
|
||||
#include "DatabaseConnectionMySQL.h" |
||||
#include "Log.h" |
||||
|
||||
DatabaseConnectionMySQL::DatabaseConnectionMySQL(MySQLConnectionInfo connInfo, DatabaseWorkQueueMySQL* asyncQueue) : |
||||
_mysql(NULL), _asyncQueue(asyncQueue), _worker(NULL), _connectionInfo(connInfo) |
||||
{ |
||||
if (_asyncQueue) { |
||||
_worker = new DatabaseWorkerMySQL(_asyncQueue, this); |
||||
Type = MYSQL_CONN_ASYNC; |
||||
} else |
||||
Type = MYSQL_CONN_SYNC; |
||||
} |
||||
|
||||
DatabaseConnectionMySQL::~DatabaseConnectionMySQL() |
||||
{ |
||||
assert(_mysql); |
||||
|
||||
for (uint32_t i = 0; i < _stmts.size(); ++i) |
||||
delete _stmts[i]; |
||||
|
||||
mysql_close(_mysql); |
||||
} |
||||
|
||||
bool DatabaseConnectionMySQL::Open() |
||||
{ |
||||
MYSQL* mysqlInit; |
||||
mysqlInit = mysql_init(NULL); |
||||
if (!mysqlInit) |
||||
{ |
||||
sLog.Error(LOG_DATABASE, "Could not initialize Mysql connection to database `%s`", _connectionInfo.DB.c_str()); |
||||
return false; |
||||
} |
||||
|
||||
mysql_options(mysqlInit, MYSQL_SET_CHARSET_NAME, "utf8"); |
||||
|
||||
_mysql = mysql_real_connect(mysqlInit, _connectionInfo.Host.c_str(), _connectionInfo.User.c_str(), |
||||
_connectionInfo.Pass.c_str(), _connectionInfo.DB.c_str(), _connectionInfo.Port, NULL, 0); |
||||
|
||||
if (_mysql) |
||||
{ |
||||
sLog.Info(LOG_DATABASE, "Connected to MySQL database at %s", _connectionInfo.Host.c_str()); |
||||
mysql_autocommit(_mysql, 1); |
||||
|
||||
// set connection properties to UTF8 to properly handle locales for different
|
||||
// server configs - core sends data in UTF8, so MySQL must expect UTF8 too
|
||||
mysql_set_character_set(_mysql, "utf8"); |
||||
|
||||
return true; |
||||
} |
||||
else |
||||
{ |
||||
sLog.Error(LOG_DATABASE, "Could not connect to MySQL database at %s: %s\n", _connectionInfo.Host.c_str(), mysql_error(mysqlInit)); |
||||
mysql_close(mysqlInit); |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
void DatabaseConnectionMySQL::Close() |
||||
{ |
||||
delete this; |
||||
} |
||||
|
||||
bool DatabaseConnectionMySQL::Execute(const char* query) |
||||
{ |
||||
sLog.Debug(LOG_DATABASE, "DatabaseConnectionMySQL::Execute(): %s", query); |
||||
|
||||
if (!query || !_mysql) |
||||
return false; |
||||
|
||||
if (mysql_query(_mysql, query)) |
||||
{ |
||||
uint32_t lErrno = mysql_errno(_mysql); |
||||
|
||||
sLog.Error(LOG_DATABASE, "[%u] %s", lErrno, mysql_error(_mysql)); |
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(query); // Try again
|
||||
|
||||
return false; |
||||
} |
||||
else |
||||
return true; |
||||
} |
||||
|
||||
ResultSetMySQL* DatabaseConnectionMySQL::Query(const char* query) |
||||
{ |
||||
sLog.Debug(LOG_DATABASE, "DatabaseConnectionMySQL::Query(): %s", query); |
||||
|
||||
if (!query) |
||||
return NULL; |
||||
|
||||
MYSQL_RES *result = NULL; |
||||
MYSQL_FIELD *fields = NULL; |
||||
uint64_t rowCount = 0; |
||||
uint32_t fieldCount = 0; |
||||
|
||||
if (!_Query(query, result, fields, rowCount, fieldCount)) |
||||
return NULL; |
||||
|
||||
return new ResultSetMySQL(result, fields, rowCount, fieldCount); |
||||
} |
||||
|
||||
bool DatabaseConnectionMySQL::_Query(const char *query, MYSQL_RES* result, MYSQL_FIELD* fields, uint64_t& rowCount, uint32_t& fieldCount) |
||||
{ |
||||
if (!_mysql) |
||||
return false; |
||||
|
||||
if (mysql_query(_mysql, query)) |
||||
{ |
||||
uint32_t lErrno = mysql_errno(_mysql); |
||||
|
||||
sLog.Error(LOG_DATABASE, "[%u] %s", lErrno, mysql_error(_mysql)); |
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return _Query(query, result, fields, rowCount, fieldCount); // We try again
|
||||
|
||||
return false; |
||||
} |
||||
|
||||
result = mysql_store_result(_mysql); |
||||
rowCount = mysql_affected_rows(_mysql); |
||||
fieldCount = mysql_field_count(_mysql); |
||||
|
||||
if (!result) |
||||
return false; |
||||
|
||||
if (!rowCount) |
||||
{ |
||||
mysql_free_result(result); |
||||
return false; |
||||
} |
||||
|
||||
fields = mysql_fetch_fields(result); |
||||
|
||||
return true; |
||||
} |
||||
|
||||
bool DatabaseConnectionMySQL::Execute(PreparedStatement* stmt) |
||||
{ |
||||
} |
||||
|
||||
ResultSetMySQL* DatabaseConnectionMySQL::Query(PreparedStatement* stmt) |
||||
{ |
||||
} |
||||
|
||||
bool DatabaseConnectionMySQL::_HandleMySQLErrno(uint32_t lErrno) |
||||
{ |
||||
return false; |
||||
} |
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
#ifndef DATABASE_CONNECTION_MYSQL_H_ |
||||
#define DATABASE_CONNECTION_MYSQL_H_ |
||||
|
||||
#include "DatabaseOperationMySQL.h" |
||||
#include "DatabaseWorkerMySQL.h" |
||||
#include "QueryResultMySQL.h" |
||||
#include "PreparedStatementMySQL.h" |
||||
|
||||
#include <boost/thread.hpp> |
||||
#include <mysql.h> |
||||
|
||||
enum MySQLConnectionType |
||||
{ |
||||
MYSQL_CONN_SYNC, |
||||
MYSQL_CONN_ASYNC, |
||||
MYSQL_CONN_SIZE |
||||
}; |
||||
|
||||
struct MySQLConnectionInfo |
||||
{ |
||||
std::string Host; |
||||
uint16_t Port; |
||||
std::string User; |
||||
std::string Pass; |
||||
std::string DB; |
||||
}; |
||||
|
||||
class DatabaseConnectionMySQL |
||||
{ |
||||
public: |
||||
DatabaseConnectionMySQL(MySQLConnectionInfo connInfo, DatabaseWorkQueueMySQL* asyncQueue = NULL); |
||||
~DatabaseConnectionMySQL(); |
||||
|
||||
bool Open(); |
||||
void Close(); |
||||
|
||||
// Ping!
|
||||
void Ping() |
||||
{ |
||||
mysql_ping(_mysql); |
||||
} |
||||
|
||||
// Queries
|
||||
bool Execute(const char* query); |
||||
ResultSetMySQL* Query(const char* query); |
||||
|
||||
// Stmt
|
||||
bool Execute(PreparedStatement* stmt); |
||||
ResultSetMySQL* Query(PreparedStatement* stmt); |
||||
|
||||
// Locking
|
||||
bool LockIfReady() |
||||
{ |
||||
return _mutex.try_lock(); |
||||
} |
||||
|
||||
void Unlock() |
||||
{ |
||||
_mutex.unlock(); |
||||
} |
||||
|
||||
MySQLConnectionType Type; |
||||
|
||||
void PrepareStatement(uint32_t index, const char* query); |
||||
|
||||
private: |
||||
bool _Query(const char *sql, MYSQL_RES* result, MYSQL_FIELD* fields, uint64_t& pRowCount, uint32_t& pFieldCount); |
||||
|
||||
bool _HandleMySQLErrno(uint32_t lErrno); |
||||
|
||||
boost::mutex _mutex; |
||||
MYSQL* _mysql; |
||||
DatabaseWorkQueueMySQL* _asyncQueue; |
||||
DatabaseWorkerMySQL* _worker; |
||||
std::vector<PreparedStatementMySQL*> _stmts; |
||||
MySQLConnectionInfo _connectionInfo; |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
#ifndef DATABASE_ENV_MYSQL_H_ |
||||
#define DATABASE_ENV_MYSQL_H_ |
||||
|
||||
#include "DatabaseWorkerPoolMySQL.h" |
||||
|
||||
#endif |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
#include "DatabaseOperationMySQL.h" |
||||
#include "DatabaseConnectionMySQL.h" |
||||
|
||||
void DatabasePingOperationMySQL::Execute() |
||||
{ |
||||
_conn->Ping(); |
||||
} |
||||
|
||||
void DatabasePreparedStatementOperationMySQL::Execute() |
||||
{ |
||||
if (_callback) { |
||||
ResultSetMySQL* result = _conn->Query(_stmt); |
||||
_callback(result); |
||||
} else |
||||
_conn->Execute(_stmt); |
||||
} |
||||
|
||||
|
||||
void DatabaseQueryOperationMySQL::Execute() |
||||
{ |
||||
if (_callback) { |
||||
ResultSetMySQL* result = _conn->Query(_query); |
||||
_callback(result); |
||||
} else |
||||
_conn->Execute(_query); |
||||
} |
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
#ifndef DATABASE_OPERATION_MYSQL_H_ |
||||
#define DATABASE_OPERATION_MYSQL_H_ |
||||
|
||||
#include "Util.h" |
||||
#include "DatabaseCallback.h" |
||||
#include "PreparedStatement.h" |
||||
#include <boost/bind.hpp> |
||||
|
||||
class DatabaseConnectionMySQL; |
||||
|
||||
class DatabaseOperationMySQL |
||||
{ |
||||
public: |
||||
DatabaseOperationMySQL(): _conn(NULL) {} |
||||
virtual void Execute() = 0; |
||||
void SetConnection(DatabaseConnectionMySQL* conn) { _conn = conn; } |
||||
protected: |
||||
DatabaseConnectionMySQL* _conn; |
||||
}; |
||||
|
||||
class DatabasePingOperationMySQL : public DatabaseOperationMySQL |
||||
{ |
||||
void Execute(); |
||||
}; |
||||
|
||||
class DatabasePreparedStatementOperationMySQL : public DatabaseOperationMySQL |
||||
{ |
||||
public: |
||||
DatabasePreparedStatementOperationMySQL(PreparedStatement* stmt, DatabaseCallback callback = NULL): DatabaseOperationMySQL(), _stmt(stmt), _callback(callback) {}; |
||||
|
||||
void Execute(); |
||||
|
||||
private: |
||||
DatabaseCallback _callback; |
||||
PreparedStatement* _stmt; |
||||
}; |
||||
|
||||
class DatabaseQueryOperationMySQL : public DatabaseOperationMySQL |
||||
{ |
||||
public: |
||||
DatabaseQueryOperationMySQL(const char* query, DatabaseCallback callback = NULL): DatabaseOperationMySQL(), _query(query), _callback(callback) {}; |
||||
|
||||
void Execute(); |
||||
|
||||
private: |
||||
DatabaseCallback _callback; |
||||
const char* _query; |
||||
}; |
||||
|
||||
typedef Util::SynchronisedQueue<DatabaseOperationMySQL*> DatabaseWorkQueueMySQL; |
||||
|
||||
#endif |
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
#include "DatabaseWorkerMySQL.h" |
||||
#include "Log.h" |
||||
|
||||
DatabaseWorkerMySQL::DatabaseWorkerMySQL(DatabaseWorkQueueMySQL* asyncQueue, DatabaseConnectionMySQL* conn) : |
||||
_asyncQueue(asyncQueue), _conn(conn) |
||||
{ |
||||
Activate(); |
||||
} |
||||
|
||||
void DatabaseWorkerMySQL::Work() |
||||
{ |
||||
sLog.Debug(LOG_DATABASE, "Database worker thread started"); |
||||
|
||||
if (!this->_asyncQueue) |
||||
return; |
||||
|
||||
DatabaseOperationMySQL* op = NULL; |
||||
for (;;) |
||||
{ |
||||
op = this->_asyncQueue->Dequeue(); |
||||
|
||||
if (!op) { |
||||
sLog.Debug(LOG_DATABASE, "Database worker thread exiting..."); |
||||
return; |
||||
} |
||||
|
||||
sLog.Debug(LOG_DATABASE, "Database worker working..."); |
||||
|
||||
op->SetConnection(_conn); |
||||
op->Execute(); |
||||
|
||||
delete op; |
||||
|
||||
sLog.Debug(LOG_DATABASE, "Database worker finished!"); |
||||
} |
||||
} |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
#ifndef DATABASE_WORKER_MYSQL_H_ |
||||
#define DATABASE_WORKER_MYSQL_H_ |
||||
|
||||
#include "Util.h" |
||||
#include "DatabaseOperationMySQL.h" |
||||
|
||||
class DatabaseConnectionMySQL; |
||||
|
||||
class DatabaseWorkerMySQL : public Util::GenericWorker |
||||
{ |
||||
public: |
||||
DatabaseWorkerMySQL(DatabaseWorkQueueMySQL* asyncQueue, DatabaseConnectionMySQL* conn); |
||||
void Work(); |
||||
private: |
||||
DatabaseWorkQueueMySQL* _asyncQueue; |
||||
DatabaseConnectionMySQL* _conn; |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,158 @@
@@ -0,0 +1,158 @@
|
||||
#ifndef DATABASE_WORKER_POOL_MYSQL_H_ |
||||
#define DATABASE_WORKER_POOL_MYSQL_H_ |
||||
|
||||
#include "Database.h" |
||||
#include "DatabaseConnectionMySQL.h" |
||||
#include "QueryResultMySQL.h" |
||||
#include "Log.h" |
||||
|
||||
#include <vector> |
||||
|
||||
class DatabaseWorkerPoolMySQL : public Database |
||||
{ |
||||
public: |
||||
DatabaseWorkerPoolMySQL() : _asyncQueue(new DatabaseWorkQueueMySQL()) { } |
||||
~DatabaseWorkerPoolMySQL() |
||||
{ |
||||
delete _asyncQueue; |
||||
} |
||||
|
||||
bool Open(MySQLConnectionInfo connInfo, uint8_t syncThreads, uint8_t asyncThreads) |
||||
{ |
||||
bool res = true; |
||||
_connectionInfo = connInfo; |
||||
|
||||
sLog.Info(LOG_DATABASE, "Opening MySQL Database Pool '%s'. Asynchronous threads: %u, synchronous threads: %u.", _connectionInfo.DB.c_str(), asyncThreads, syncThreads); |
||||
|
||||
for (uint8_t i = 0; i < syncThreads; ++i) |
||||
{ |
||||
DatabaseConnectionMySQL* conn = new DatabaseConnectionMySQL(_connectionInfo); |
||||
res &= conn->Open(); |
||||
_connections[MYSQL_CONN_SYNC].push_back(conn); |
||||
} |
||||
|
||||
for (uint8_t i = 0; i < syncThreads; ++i) |
||||
{ |
||||
DatabaseConnectionMySQL* conn = new DatabaseConnectionMySQL(_connectionInfo, _asyncQueue); |
||||
res &= conn->Open(); |
||||
_connections[MYSQL_CONN_ASYNC].push_back(conn); |
||||
} |
||||
|
||||
if (res) |
||||
sLog.Info(LOG_DATABASE, "MySQL Database Pool '%s' opened successfully. %u total connections.", _connectionInfo.DB.c_str(), _connections[MYSQL_CONN_SYNC].size()+_connections[MYSQL_CONN_ASYNC].size()); |
||||
else |
||||
sLog.Error(LOG_DATABASE, "Failed opening MySQL Database Pool to '%s'.", _connectionInfo.DB.c_str()); |
||||
|
||||
return res; |
||||
} |
||||
|
||||
void Close() |
||||
{ |
||||
sLog.Info(LOG_DATABASE, "Closing MySQL Database Pool '%s'.", _connectionInfo.DB.c_str()); |
||||
|
||||
// Stop worker threads
|
||||
_asyncQueue->Stop(); |
||||
|
||||
for (uint8_t i = 0; i < _connections[MYSQL_CONN_SYNC].size(); ++i) |
||||
{ |
||||
DatabaseConnectionMySQL* conn = _connections[MYSQL_CONN_SYNC][i]; |
||||
conn->Close(); |
||||
} |
||||
|
||||
for (uint8_t i = 0; i < _connections[MYSQL_CONN_ASYNC].size(); ++i) |
||||
{ |
||||
DatabaseConnectionMySQL* conn = _connections[MYSQL_CONN_ASYNC][i]; |
||||
conn->Close(); |
||||
} |
||||
|
||||
sLog.Info(LOG_DATABASE, "Closed all connections to MySQL Database Pool '%s'.", _connectionInfo.DB.c_str()); |
||||
} |
||||
|
||||
// Queries
|
||||
bool Execute(const char* query) |
||||
{ |
||||
DatabaseConnectionMySQL* conn = GetSyncConnection(); |
||||
bool result = conn->Execute(query); |
||||
conn->Unlock(); |
||||
return result; |
||||
} |
||||
ResultSetMySQL* Query(const char* query) |
||||
{ |
||||
DatabaseConnectionMySQL* conn = GetSyncConnection(); |
||||
ResultSetMySQL* result = conn->Query(query); |
||||
conn->Unlock(); |
||||
return result; |
||||
} |
||||
|
||||
// Stmt
|
||||
bool Execute(PreparedStatement* stmt) |
||||
{ |
||||
DatabaseConnectionMySQL* conn = GetSyncConnection(); |
||||
bool result = conn->Execute(stmt); |
||||
conn->Unlock(); |
||||
return result; |
||||
} |
||||
ResultSetMySQL* Query(PreparedStatement* stmt) |
||||
{ |
||||
DatabaseConnectionMySQL* conn = GetSyncConnection(); |
||||
ResultSetMySQL* result = conn->Query(stmt); |
||||
conn->Unlock(); |
||||
return result; |
||||
} |
||||
|
||||
// Async
|
||||
bool ExecuteAsync(const char* query) |
||||
{ |
||||
DatabaseQueryOperationMySQL* op = new DatabaseQueryOperationMySQL(query); |
||||
_asyncQueue->Enqueue(op); |
||||
return true; |
||||
} |
||||
bool ExecuteAsync(PreparedStatement* stmt) |
||||
{ |
||||
DatabasePreparedStatementOperationMySQL* op = new DatabasePreparedStatementOperationMySQL(stmt); |
||||
_asyncQueue->Enqueue(op); |
||||
return true; |
||||
} |
||||
bool QueryAsync(DatabaseCallback callback, const char* query) |
||||
{ |
||||
DatabaseQueryOperationMySQL* op = new DatabaseQueryOperationMySQL(query, callback); |
||||
_asyncQueue->Enqueue(op); |
||||
return true; |
||||
} |
||||
bool QueryAsync(DatabaseCallback callback, PreparedStatement* stmt) |
||||
{ |
||||
DatabasePreparedStatementOperationMySQL* op = new DatabasePreparedStatementOperationMySQL(stmt, callback); |
||||
_asyncQueue->Enqueue(op); |
||||
return true; |
||||
} |
||||
|
||||
// Prepared Statements
|
||||
PreparedStatement* GetPreparedStatement(uint32_t stmtid) |
||||
{ |
||||
return NULL;//new PreparedStatement(stmtid);
|
||||
} |
||||
|
||||
private: |
||||
DatabaseConnectionMySQL* GetSyncConnection() |
||||
{ |
||||
uint32_t i; |
||||
uint8_t conn_size = _connections[MYSQL_CONN_SYNC].size(); |
||||
DatabaseConnectionMySQL* conn = NULL; |
||||
|
||||
// Block until we find a free connection
|
||||
for (;;) |
||||
{ |
||||
conn = _connections[MYSQL_CONN_SYNC][++i % conn_size]; |
||||
if (conn->LockIfReady()) |
||||
break; |
||||
} |
||||
|
||||
return conn; |
||||
} |
||||
|
||||
std::vector<DatabaseConnectionMySQL*> _connections[MYSQL_CONN_SIZE]; |
||||
MySQLConnectionInfo _connectionInfo; |
||||
DatabaseWorkQueueMySQL* _asyncQueue; |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
#ifndef FIELD_MYSQL_H_ |
||||
#define FIELD_MYSQL_H_ |
||||
|
||||
#include "Field.h" |
||||
|
||||
class FieldMySQL : public Field |
||||
{ |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
#include "PreparedStatementMySQL.h" |
||||
#include <cstring> |
||||
|
||||
PreparedStatementMySQL::PreparedStatementMySQL(MYSQL_STMT* stmt) : |
||||
_stmt(stmt), _bind(NULL), PreparedStatement(0) |
||||
{ |
||||
_paramCount = mysql_stmt_param_count(stmt); |
||||
_bind = new MYSQL_BIND[_paramCount]; |
||||
memset(_bind, 0, sizeof(MYSQL_BIND)*_paramCount); |
||||
} |
||||
|
||||
PreparedStatementMySQL::~PreparedStatementMySQL() |
||||
{ |
||||
ClearParameters(); |
||||
if (_stmt->bind_result_done) |
||||
{ |
||||
delete[] _stmt->bind->length; |
||||
delete[] _stmt->bind->is_null; |
||||
} |
||||
mysql_stmt_close(_stmt); |
||||
delete[] _bind; |
||||
this->~PreparedStatement(); |
||||
} |
||||
|
||||
void PreparedStatementMySQL::ClearParameters() |
||||
{ |
||||
for (uint8_t i = 0; i < _paramCount; ++i) |
||||
{ |
||||
delete _bind[i].length; |
||||
_bind[i].length = NULL; |
||||
delete[] (char*) _bind[i].buffer; |
||||
_bind[i].buffer = NULL; |
||||
} |
||||
} |
@ -0,0 +1,24 @@
@@ -0,0 +1,24 @@
|
||||
#ifndef PREPARED_STATEMENT_MYSQL_H_ |
||||
#define PREPARED_STATEMENT_MYSQL_H_ |
||||
|
||||
#include "PreparedStatement.h" |
||||
#include <boost/cstdint.hpp> |
||||
#include <mysql.h> |
||||
|
||||
class PreparedStatementMySQL : public PreparedStatement |
||||
{ |
||||
public: |
||||
PreparedStatementMySQL(MYSQL_STMT* stmt); |
||||
~PreparedStatementMySQL(); |
||||
|
||||
template<class T> |
||||
void Set(const uint8_t index, const T value); |
||||
|
||||
void ClearParameters(); |
||||
private: |
||||
MYSQL_STMT* _stmt; |
||||
MYSQL_BIND* _bind; |
||||
uint8_t _paramCount; |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
#include "QueryResultMySQL.h" |
||||
|
||||
ResultSetMySQL::ResultSetMySQL(MYSQL_RES* result, MYSQL_FIELD* fields, uint64_t rowCount, uint32_t fieldCount) |
||||
{ |
||||
} |
||||
|
||||
ResultSetMySQL::~ResultSetMySQL() |
||||
{ |
||||
} |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
#ifndef QUERY_RESULT_MYSQL_H_ |
||||
#define QUERY_RESULT_MYSQL_H_ |
||||
|
||||
#include "QueryResult.h" |
||||
#include "FieldMySQL.h" |
||||
#include <boost/shared_ptr.hpp> |
||||
#include <cassert> |
||||
#include <mysql.h> |
||||
|
||||
class ResultSetMySQL : public ResultSet |
||||
{ |
||||
public: |
||||
ResultSetMySQL(MYSQL_RES* result, MYSQL_FIELD* fields, uint64_t rowCount, uint32_t fieldCount); |
||||
~ResultSetMySQL(); |
||||
|
||||
// Metadata
|
||||
uint64_t GetRowCount() |
||||
{ |
||||
return _rowCount; |
||||
} |
||||
|
||||
uint32_t GetFieldCount() |
||||
{ |
||||
return _fieldCount; |
||||
} |
||||
|
||||
bool NextRow() {}; |
||||
Field* Fetch() {}; |
||||
|
||||
private: |
||||
uint64_t _rowCount; |
||||
FieldMySQL* _currentRow; |
||||
uint32_t _fieldCount; |
||||
void CleanUp(); |
||||
MYSQL_RES* _result; |
||||
MYSQL_FIELD* _fields; |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
#ifndef PREPARED_STATEMENT_H_ |
||||
#define PREPARED_STATEMENT_H_ |
||||
|
||||
#include <boost/cstdint.hpp> |
||||
|
||||
class PreparedStatement |
||||
{ |
||||
public: |
||||
PreparedStatement(uint32_t index) {}; |
||||
}; |
||||
|
||||
#endif |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
#ifndef RESULTSET_H_ |
||||
#define RESULTSET_H_ |
||||
|
||||
#include "Field.h" |
||||
#include <boost/shared_ptr.hpp> |
||||
#include <boost/cstdint.hpp> |
||||
|
||||
class ResultSet |
||||
{ |
||||
public: |
||||
// Metadata
|
||||
virtual uint64_t GetRowCount() = 0; |
||||
virtual uint32_t GetFieldCount() = 0; |
||||
|
||||
virtual bool NextRow() = 0; |
||||
virtual Field* Fetch() = 0; |
||||
}; |
||||
|
||||
typedef boost::shared_ptr<ResultSet> QueryResult; |
||||
|
||||
#endif |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
#include "Util.h" |
||||
|
||||
std::string Util::Date(const char* format, bool utc) |
||||
{ |
||||
boost::posix_time::ptime now; |
||||
if (utc) |
||||
now = boost::posix_time::second_clock::universal_time(); |
||||
else |
||||
now = boost::posix_time::second_clock::local_time(); |
||||
|
||||
std::stringstream ss; |
||||
boost::posix_time::time_facet *facet = new boost::posix_time::time_facet(format); |
||||
ss.imbue(std::locale(std::cout.getloc(), facet)); |
||||
ss << now; |
||||
|
||||
return ss.str(); |
||||
} |
Loading…
Reference in new issue