diff options
Diffstat (limited to 'src/server/shared/Database')
-rw-r--r-- | src/server/shared/Database/AsyncDatabaseImpl.h | 250 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseEnv.h | 8 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseImpl.h | 234 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseWorker.cpp | 67 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseWorker.h | 42 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseWorkerPool.cpp | 216 | ||||
-rw-r--r-- | src/server/shared/Database/DatabaseWorkerPool.h | 157 | ||||
-rw-r--r-- | src/server/shared/Database/MySQLConnection.cpp | 244 | ||||
-rw-r--r-- | src/server/shared/Database/MySQLConnection.h | 56 | ||||
-rw-r--r-- | src/server/shared/Database/MySQLThreading.h | 53 | ||||
-rw-r--r-- | src/server/shared/Database/PreparedStatements.cpp | 93 | ||||
-rw-r--r-- | src/server/shared/Database/PreparedStatements.h | 30 | ||||
-rw-r--r-- | src/server/shared/Database/SQLOperation.cpp (renamed from src/server/shared/Database/SqlOperations.cpp) | 149 | ||||
-rw-r--r-- | src/server/shared/Database/SQLOperation.h | 122 | ||||
-rw-r--r-- | src/server/shared/Database/SQLStorage.cpp | 2 | ||||
-rw-r--r-- | src/server/shared/Database/SqlOperations.h | 168 |
16 files changed, 1290 insertions, 601 deletions
diff --git a/src/server/shared/Database/AsyncDatabaseImpl.h b/src/server/shared/Database/AsyncDatabaseImpl.h new file mode 100644 index 00000000000..f85540a8016 --- /dev/null +++ b/src/server/shared/Database/AsyncDatabaseImpl.h @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> + * + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#include "Database/DatabaseWorkerPool.h" +#include "Database/SQLOperation.h" + + +/// Function body definitions for the template function members of the Database class + +#define ASYNC_QUERY_BODY(sql, queue_itr) \ + if (!sql) return false; \ + \ + QueryQueues::iterator queue_itr; \ + \ + { \ + ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \ + queue_itr = m_queryQueues.find(queryThread); \ + if (queue_itr == m_queryQueues.end()) return false; \ + } + +#define ASYNC_PQUERY_BODY(format, szQuery) \ + if(!format) return false; \ + \ + char szQuery [MAX_QUERY_LEN]; \ + \ + { \ + va_list ap; \ + \ + va_start(ap, format); \ + int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); \ + va_end(ap); \ + \ + if(res==-1) \ + { \ + sLog.outError("SQL Query truncated (and not execute) for format: %s",format); \ + return false; \ + } \ + } + + +#define ASYNC_DELAYHOLDER_BODY(holder, queue_itr) \ + if (!holder) return false; \ + \ + QueryQueues::iterator queue_itr; \ + \ + { \ + ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \ + queue_itr = m_queryQueues.find(queryThread); \ + if (queue_itr == m_queryQueues.end()) return false; \ + } + + +// -- Query / member -- + + +template<class Class> +bool +DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *sql) +{ + ASYNC_QUERY_BODY(sql, itr) + SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class>(object, method), itr->second); + Enqueue(task); + return true; +} + + +template<class Class, typename ParamType1> +bool +DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql) +{ + ASYNC_QUERY_BODY(sql, itr) + SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, param1), itr->second); + Enqueue(task); + return true; +} + + +template<class Class, typename ParamType1, typename ParamType2> +bool +DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) +{ + ASYNC_QUERY_BODY(sql, itr) + SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2>(object, method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second); + Enqueue(task); + return true; +} + + +template<class Class, typename ParamType1, typename ParamType2, typename ParamType3> +bool +DatabaseWorkerPool::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql) +{ + ASYNC_QUERY_BODY(sql, itr) + SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2, ParamType3>(object, method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second); + Enqueue(task); + return true; +} + + +// -- Query / static -- + + +template<typename ParamType1> +bool +DatabaseWorkerPool::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql) +{ + ASYNC_QUERY_BODY(sql, itr) + SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::SQueryCallback<ParamType1>(method, (QueryResult_AutoPtr)NULL, param1), itr->second); + Enqueue(task); + return true; +} + + +template<typename ParamType1, typename ParamType2> +bool +DatabaseWorkerPool::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) +{ + ASYNC_QUERY_BODY(sql, itr) + SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::SQueryCallback<ParamType1, ParamType2>(method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second); + Enqueue(task); + return true; +} + + +template<typename ParamType1, typename ParamType2, typename ParamType3> +bool +DatabaseWorkerPool::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql) +{ + ASYNC_QUERY_BODY(sql, itr) + SQLQueryTask* task = new SQLQueryTask(sql, new Trinity::SQueryCallback<ParamType1, ParamType2, ParamType3>(method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second); + Enqueue(task); + return true; +} + + +// -- PQuery / member -- + + +template<class Class> +bool +DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *format,...) +{ + ASYNC_PQUERY_BODY(format, szQuery) + return AsyncQuery(object, method, szQuery); +} + + +template<class Class, typename ParamType1> +bool +DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) +{ + ASYNC_PQUERY_BODY(format, szQuery) + return AsyncQuery(object, method, param1, szQuery); +} + + +template<class Class, typename ParamType1, typename ParamType2> +bool +DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) +{ + ASYNC_PQUERY_BODY(format, szQuery) + return AsyncQuery(object, method, param1, param2, szQuery); +} + + +template<class Class, typename ParamType1, typename ParamType2, typename ParamType3> +bool +DatabaseWorkerPool::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) +{ + ASYNC_PQUERY_BODY(format, szQuery) + return AsyncQuery(object, method, param1, param2, param3, szQuery); +} + + +// -- PQuery / static -- + + +template<typename ParamType1> +bool +DatabaseWorkerPool::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) +{ + ASYNC_PQUERY_BODY(format, szQuery) + return AsyncQuery(method, param1, szQuery); +} + + +template<typename ParamType1, typename ParamType2> +bool +DatabaseWorkerPool::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) +{ + ASYNC_PQUERY_BODY(format, szQuery) + return AsyncQuery(method, param1, param2, szQuery); +} + + +template<typename ParamType1, typename ParamType2, typename ParamType3> +bool +DatabaseWorkerPool::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) +{ + ASYNC_PQUERY_BODY(format, szQuery) + return AsyncQuery(method, param1, param2, param3, szQuery); +} + + +// -- QueryHolder -- + + +template<class Class> +bool +DatabaseWorkerPool::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*), SQLQueryHolder *holder) +{ + ASYNC_DELAYHOLDER_BODY(holder, itr) + SQLQueryHolderTask *task = new SQLQueryHolderTask(holder, new Trinity::QueryCallback<Class, SQLQueryHolder*>(object, method, (QueryResult_AutoPtr)NULL, holder), itr->second); + Enqueue(task); + return true; +} + + +template<class Class, typename ParamType1> +bool +DatabaseWorkerPool::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*, ParamType1), SQLQueryHolder *holder, ParamType1 param1) +{ + ASYNC_DELAYHOLDER_BODY(holder, itr) + SQLQueryHolderTask *task = new SQLQueryHolderTask(holder, new Trinity::QueryCallback<Class, SQLQueryHolder*, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, holder, param1), itr->second); + Enqueue(task); + return true; +} + + +#undef ASYNC_QUERY_BODY +#undef ASYNC_PQUERY_BODY +#undef ASYNC_DELAYHOLDER_BODY diff --git a/src/server/shared/Database/DatabaseEnv.h b/src/server/shared/Database/DatabaseEnv.h index 15c1b1c599e..398ae66f235 100644 --- a/src/server/shared/Database/DatabaseEnv.h +++ b/src/server/shared/Database/DatabaseEnv.h @@ -28,8 +28,10 @@ #include "Database/Field.h" #include "Database/QueryResult.h" -#include "Database/Database.h" -typedef Database DatabaseType; +#include "Database/DatabaseWorkerPool.h" +#include "Database/MySQLThreading.h" + +typedef DatabaseWorkerPool DatabaseType; #define _LIKE_ "LIKE" #define _TABLE_SIM_ "`" #define _CONCAT3_(A,B,C) "CONCAT( " A " , " B " , " C " )" @@ -39,5 +41,7 @@ extern DatabaseType WorldDatabase; extern DatabaseType CharacterDatabase; extern DatabaseType LoginDatabase; +#define MAX_QUERY_LEN 32*1024 + #endif diff --git a/src/server/shared/Database/DatabaseImpl.h b/src/server/shared/Database/DatabaseImpl.h deleted file mode 100644 index f0ba9c84a30..00000000000 --- a/src/server/shared/Database/DatabaseImpl.h +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -#include "Database/Database.h" -#include "Database/SqlOperations.h" - - -/// Function body definitions for the template function members of the Database class - - -#define ASYNC_QUERY_BODY(sql, queue_itr) \ - if (!sql) return false; \ - \ - QueryQueues::iterator queue_itr; \ - \ - { \ - ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \ - queue_itr = m_queryQueues.find(queryThread); \ - if (queue_itr == m_queryQueues.end()) return false; \ - } - - -#define ASYNC_PQUERY_BODY(format, szQuery) \ - if(!format) return false; \ - \ - char szQuery [MAX_QUERY_LEN]; \ - \ - { \ - va_list ap; \ - \ - va_start(ap, format); \ - int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); \ - va_end(ap); \ - \ - if(res==-1) \ - { \ - sLog.outError("SQL Query truncated (and not execute) for format: %s",format); \ - return false; \ - } \ - } - - -#define ASYNC_DELAYHOLDER_BODY(holder, queue_itr) \ - if (!holder) return false; \ - \ - QueryQueues::iterator queue_itr; \ - \ - { \ - ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \ - queue_itr = m_queryQueues.find(queryThread); \ - if (queue_itr == m_queryQueues.end()) return false; \ - } - - -// -- Query / member -- - - -template<class Class> -bool -Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *sql) -{ - ASYNC_QUERY_BODY(sql, itr) - return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class>(object, method), itr->second)); -} - - -template<class Class, typename ParamType1> -bool -Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql) -{ - ASYNC_QUERY_BODY(sql, itr) - return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, param1), itr->second)); -} - - -template<class Class, typename ParamType1, typename ParamType2> -bool -Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) -{ - ASYNC_QUERY_BODY(sql, itr) - return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2>(object, method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second)); -} - - -template<class Class, typename ParamType1, typename ParamType2, typename ParamType3> -bool -Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql) -{ - ASYNC_QUERY_BODY(sql, itr) - return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2, ParamType3>(object, method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second)); -} - - -// -- Query / static -- - - -template<typename ParamType1> -bool -Database::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql) -{ - ASYNC_QUERY_BODY(sql, itr) - return m_threadBody->Delay(new SqlQuery(sql, new Trinity::SQueryCallback<ParamType1>(method, (QueryResult_AutoPtr)NULL, param1), itr->second)); -} - - -template<typename ParamType1, typename ParamType2> -bool -Database::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) -{ - ASYNC_QUERY_BODY(sql, itr) - return m_threadBody->Delay(new SqlQuery(sql, new Trinity::SQueryCallback<ParamType1, ParamType2>(method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second)); -} - - -template<typename ParamType1, typename ParamType2, typename ParamType3> -bool -Database::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql) -{ - ASYNC_QUERY_BODY(sql, itr) - return m_threadBody->Delay(new SqlQuery(sql, new Trinity::SQueryCallback<ParamType1, ParamType2, ParamType3>(method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second)); -} - - -// -- PQuery / member -- - - -template<class Class> -bool -Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *format,...) -{ - ASYNC_PQUERY_BODY(format, szQuery) - return AsyncQuery(object, method, szQuery); -} - - -template<class Class, typename ParamType1> -bool -Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) -{ - ASYNC_PQUERY_BODY(format, szQuery) - return AsyncQuery(object, method, param1, szQuery); -} - - -template<class Class, typename ParamType1, typename ParamType2> -bool -Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) -{ - ASYNC_PQUERY_BODY(format, szQuery) - return AsyncQuery(object, method, param1, param2, szQuery); -} - - -template<class Class, typename ParamType1, typename ParamType2, typename ParamType3> -bool -Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) -{ - ASYNC_PQUERY_BODY(format, szQuery) - return AsyncQuery(object, method, param1, param2, param3, szQuery); -} - - -// -- PQuery / static -- - - -template<typename ParamType1> -bool -Database::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) -{ - ASYNC_PQUERY_BODY(format, szQuery) - return AsyncQuery(method, param1, szQuery); -} - - -template<typename ParamType1, typename ParamType2> -bool -Database::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) -{ - ASYNC_PQUERY_BODY(format, szQuery) - return AsyncQuery(method, param1, param2, szQuery); -} - - -template<typename ParamType1, typename ParamType2, typename ParamType3> -bool -Database::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) -{ - ASYNC_PQUERY_BODY(format, szQuery) - return AsyncQuery(method, param1, param2, param3, szQuery); -} - - -// -- QueryHolder -- - - -template<class Class> -bool -Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SqlQueryHolder*), SqlQueryHolder *holder) -{ - ASYNC_DELAYHOLDER_BODY(holder, itr) - return holder->Execute(new Trinity::QueryCallback<Class, SqlQueryHolder*>(object, method, (QueryResult_AutoPtr)NULL, holder), m_threadBody, itr->second); -} - - -template<class Class, typename ParamType1> -bool -Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1) -{ - ASYNC_DELAYHOLDER_BODY(holder, itr) - return holder->Execute(new Trinity::QueryCallback<Class, SqlQueryHolder*, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, holder, param1), m_threadBody, itr->second); -} - - -#undef ASYNC_QUERY_BODY -#undef ASYNC_PQUERY_BODY -#undef ASYNC_DELAYHOLDER_BODY diff --git a/src/server/shared/Database/DatabaseWorker.cpp b/src/server/shared/Database/DatabaseWorker.cpp new file mode 100644 index 00000000000..17fc1d75a5d --- /dev/null +++ b/src/server/shared/Database/DatabaseWorker.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "DatabaseEnv.h" +#include "DatabaseWorker.h" +#include "SQLOperation.h" +#include "MySQLConnection.h" + +DatabaseWorker::DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con) : +m_queue(new_queue), +m_conn(con) +{ + /// Assign thread to task + activate(); +} + +int DatabaseWorker::svc() +{ + if (!m_queue) + return -1; + + SQLOperation *request = NULL; + while (1) + { + request = (SQLOperation*)(m_queue->dequeue()); + if (!request) + break; + + request->SetConnection(m_conn); + request->call(); + delete request; + } + + delete m_conn; + delete this; + return 0; +} + +int DatabaseWorker::activate() +{ + /* THR_DETACHED: + Create an asynchronous thread. The exit status of the thread would not be available to any other threads. + The thread resources are reclaimed by the operating system whenever the thread is terminated. */ + + /* THR_NEW_LWP: + Create an explicit kernel-level thread (as opposed to a user-level thread). */ + + ACE_Task_Base::activate(THR_NEW_LWP | THR_DETACHED, 1); + return 0; //^ - Spawn one thread to handle this task. + // However more of these tasks may be activated + // See DatabaseWorkerPool ctor. +}
\ No newline at end of file diff --git a/src/server/shared/Database/DatabaseWorker.h b/src/server/shared/Database/DatabaseWorker.h new file mode 100644 index 00000000000..ad5102d28ca --- /dev/null +++ b/src/server/shared/Database/DatabaseWorker.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _WORKERTHREAD_H +#define _WORKERTHREAD_H + +#include <ace/Task.h> +#include <ace/Activation_Queue.h> + +class MySQLConnection; + +class DatabaseWorker : protected ACE_Task_Base +{ + public: + DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con); + + ///- Inherited from ACE_Task_Base + int svc(); + int activate(); + + private: + DatabaseWorker() : ACE_Task_Base() {} + ACE_Activation_Queue* m_queue; + MySQLConnection* m_conn; +}; + +#endif
\ No newline at end of file diff --git a/src/server/shared/Database/DatabaseWorkerPool.cpp b/src/server/shared/Database/DatabaseWorkerPool.cpp new file mode 100644 index 00000000000..532d9cad7df --- /dev/null +++ b/src/server/shared/Database/DatabaseWorkerPool.cpp @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "DatabaseWorkerPool.h" +#include "MySQLConnection.h" +#include "DatabaseEnv.h" +#include "SQLOperation.h" + +DatabaseWorkerPool::DatabaseWorkerPool() : +m_queue(new ACE_Activation_Queue(new ACE_Message_Queue<ACE_MT_SYNCH>)), +m_connections(0) +{ + m_infoString = ""; + + mysql_library_init(-1, NULL, NULL); + WPFatal (mysql_thread_safe(), "Used MySQL library isn't thread-safe."); +} + +DatabaseWorkerPool::~DatabaseWorkerPool() +{ +} + +bool DatabaseWorkerPool::Open(const std::string& infoString, uint8 num_threads) +{ + sLog.outDebug("Creating bundled/master MySQL connection."); + m_bundle_conn = new MySQLConnection(); + m_bundle_conn->Open(infoString); + ++m_connections; + + m_async_connections.resize(num_threads); + + /// Open the Async pool + for (uint8 i = 0; i < num_threads; i++) + { + m_async_connections[i] = new MySQLConnection(m_queue); + m_async_connections[i]->Open(infoString); + ++m_connections; + sLog.outDebug("Async database thread pool opened. Worker thread count: %u", num_threads); + } + + m_infoString = infoString; + return true; +} + +void DatabaseWorkerPool::Close() +{ + /// Shuts down worker threads for this connection pool. + for (uint8 i = 0; i < m_async_connections.size(); i++) + Enqueue(NULL); + + //- MySQL::Thread_End() should be called manually from the aborting calling threads + + delete m_bundle_conn; + m_bundle_conn = NULL; +} + +/*! This function creates a new MySQL connection for every MapUpdate thread + and every unbundled task. + */ +void DatabaseWorkerPool::Init_MySQL_Connection() +{ + MySQLConnection* conn = new MySQLConnection(); + conn->Open(m_infoString); + + { + ACE_Guard<ACE_Thread_Mutex> guard(m_connectionMap_mtx); + m_sync_connections[ACE_Based::Thread::current()] = conn; + } + + sLog.outDebug("Core thread with ID ["UI64FMTD"] initializing MySQL connection.", + (uint64)ACE_Based::Thread::currentId()); +} + +void DatabaseWorkerPool::End_MySQL_Connection() +{ + MySQLConnection* conn; + { + ACE_Guard<ACE_Thread_Mutex> guard(m_connectionMap_mtx); + conn = m_sync_connections[ACE_Based::Thread::current()]; + } + delete conn; + conn = NULL; +} + +void DatabaseWorkerPool::Execute(const char* sql) +{ + if (!sql) + return; + + BasicStatementTask* task = new BasicStatementTask(sql); + Enqueue(task); +} + +void DatabaseWorkerPool::PExecute(const char* sql, ...) +{ + if (!sql) + return; + + va_list ap; + char szQuery[MAX_QUERY_LEN]; + va_start(ap, sql); + int res = vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap); + va_end(ap); + + Execute(szQuery); +} + +void DatabaseWorkerPool::DirectExecute(const char* sql) +{ + if (sql) + GetConnection()->Execute(sql); +} + +void DatabaseWorkerPool::DirectPExecute(const char* sql, ...) +{ + if (!sql) + return; + + va_list ap; + char szQuery[MAX_QUERY_LEN]; + va_start(ap, sql); + int res = vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap); + va_end(ap); + + return DirectExecute(szQuery); +} + +QueryResult_AutoPtr DatabaseWorkerPool::Query(const char* sql) +{ + return GetConnection()->Query(sql); +} + +QueryResult_AutoPtr DatabaseWorkerPool::PQuery(const char* sql, ...) +{ + if (!sql) + return QueryResult_AutoPtr(NULL); + + va_list ap; + char szQuery[MAX_QUERY_LEN]; + va_start(ap, sql); + int res = vsnprintf(szQuery, MAX_QUERY_LEN, sql, ap); + va_end(ap); + + return Query(szQuery); +} + +void DatabaseWorkerPool::BeginTransaction() +{ + ACE_Guard<ACE_Thread_Mutex> guard(m_transQueues_mtx); + ACE_Based::Thread* tranThread = ACE_Based::Thread::current(); // owner of this transaction + TransactionQueues::iterator itr = m_tranQueues.find(tranThread); + if (itr != m_tranQueues.end() && itr->second != NULL) + { + itr->second->ForcefulDelete(); + delete itr->second; + } + m_tranQueues[tranThread] = new TransactionTask(); + return; +} + +void DatabaseWorkerPool::RollbackTransaction() +{ + ACE_Guard<ACE_Thread_Mutex> guard(m_transQueues_mtx); + ACE_Based::Thread* tranThread = ACE_Based::Thread::current(); // owner of this transaction + TransactionQueues::iterator itr = m_tranQueues.find(tranThread); + if (itr != m_tranQueues.end() && itr->second != NULL) + { + itr->second->ForcefulDelete(); + delete itr->second; + } +} + +void DatabaseWorkerPool::CommitTransaction() +{ + ACE_Guard<ACE_Thread_Mutex> guard(m_transQueues_mtx); + ACE_Based::Thread* tranThread = ACE_Based::Thread::current(); // owner of this transaction + TransactionQueues::iterator itr = m_tranQueues.find(tranThread); + if (itr != m_tranQueues.end() && itr->second != NULL) + { + Enqueue(itr->second); + m_tranQueues.erase(itr); + } +} + + +MySQLConnection* DatabaseWorkerPool::GetConnection() +{ + MySQLConnection* conn; + ConnectionMap::const_iterator itr; + { + /*! MapUpdate + unbundled threads */ + ACE_Guard<ACE_Thread_Mutex> guard(m_connectionMap_mtx); + itr = m_sync_connections.find(ACE_Based::Thread::current()); + if (itr != m_sync_connections.end()) + conn = itr->second; + } + /*! Bundled threads */ + conn = m_bundle_conn; + ASSERT (conn); + return conn; +}
\ No newline at end of file diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/shared/Database/DatabaseWorkerPool.h new file mode 100644 index 00000000000..d6275e0307f --- /dev/null +++ b/src/server/shared/Database/DatabaseWorkerPool.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _DATABASEWORKERPOOL_H +#define _DATABASEWORKERPOOL_H + +#include "Common.h" +#include "Logging/Log.h" + +#include <ace/Activation_Queue.h> +#include <ace/Atomic_Op_T.h> +#include <ace/Thread_Mutex.h> + +#include "SQLOperation.h" +#include "QueryResult.h" +#include "MySQLConnection.h" + +enum MySQLThreadBundle +{ + MYSQL_BUNDLE_NONE = 0x00, //- Each task will run their own MySQL connection + MYSQL_BUNDLE_CLI = 0x01, //- Commandline interface thread + MYSQL_BUNDLE_RA = 0x02, //- Remote admin thread + MYSQL_BUNDLE_RAR = 0x04, //- Reactor runnable thread + MYSQL_BUNDLE_WORLD = 0x08, //- WorldRunnable + MYSQL_BUNDLE_ALL = MYSQL_BUNDLE_CLI | MYSQL_BUNDLE_RA | MYSQL_BUNDLE_RAR | MYSQL_BUNDLE_WORLD, +}; + +class DatabaseWorkerPool +{ + public: + DatabaseWorkerPool(); + ~DatabaseWorkerPool(); + + bool Open(const std::string& infoString, uint8 num_threads); + void Close(); + + void Init_MySQL_Connection(); + void End_MySQL_Connection(); + + void Execute(const char* sql); + void PExecute(const char* sql, ...); + void DirectExecute(const char* sql); + void DirectPExecute(const char* sql, ...); + QueryResult_AutoPtr Query(const char* sql); + QueryResult_AutoPtr PQuery(const char* sql, ...); + + /// Async queries and query holders, implemented in DatabaseImpl.h + + // Query / member + template<class Class> + bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *sql); + template<class Class, typename ParamType1> + bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql); + template<class Class, typename ParamType1, typename ParamType2> + bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql); + template<class Class, typename ParamType1, typename ParamType2, typename ParamType3> + bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql); + // Query / static + template<typename ParamType1> + bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql); + template<typename ParamType1, typename ParamType2> + bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql); + template<typename ParamType1, typename ParamType2, typename ParamType3> + bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql); + // PQuery / member + template<class Class> + bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *format,...) ATTR_PRINTF(4,5); + template<class Class, typename ParamType1> + bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6); + template<class Class, typename ParamType1, typename ParamType2> + bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(6,7); + template<class Class, typename ParamType1, typename ParamType2, typename ParamType3> + bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(7,8); + // PQuery / static + template<typename ParamType1> + bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(4,5); + template<typename ParamType1, typename ParamType2> + bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6); + template<typename ParamType1, typename ParamType2, typename ParamType3> + bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(6,7); + template<class Class> + // QueryHolder + bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*), SQLQueryHolder *holder); + template<class Class, typename ParamType1> + bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SQLQueryHolder*, ParamType1), SQLQueryHolder *holder, ParamType1 param1); + + void SetResultQueue(SQLResultQueue * queue) + { + m_queryQueues[ACE_Based::Thread::current()] = queue; + } + + void BeginTransaction(); + void RollbackTransaction(); + void CommitTransaction(); + + void escape_string(std::string& str) + { + if (str.empty()) + return; + + char* buf = new char[str.size()*2+1]; + escape_string(buf,str.c_str(),str.size()); + str = buf; + delete[] buf; + } + + unsigned long escape_string(char *to, const char *from, unsigned long length) + { + if (!to || !from || !length) + return 0; + return (mysql_real_escape_string(GetConnection()->GetHandle(), to, from, length)); + } + + private: + void Enqueue(SQLOperation* op) + { + m_queue->enqueue(op); + } + + MySQLConnection* GetConnection(); + + private: + typedef UNORDERED_MAP<ACE_Based::Thread*, MySQLConnection*> ConnectionMap; + typedef UNORDERED_MAP<ACE_Based::Thread*, TransactionTask*> TransactionQueues; + typedef UNORDERED_MAP<ACE_Based::Thread*, SQLResultQueue*> QueryQueues; + typedef ACE_Atomic_Op<ACE_SYNCH_MUTEX, uint32> AtomicUInt; + + private: + ACE_Activation_Queue* m_queue; //! Queue shared by async worker threads. + ACE_Thread_Mutex m_queue_mtx; //! For thread safe enqueues of delayed statements. + std::vector<MySQLConnection*> m_async_connections; + ConnectionMap m_sync_connections; //! Holds a mysql connection+thread per mapUpdate thread and unbundled runnnables. + ACE_Thread_Mutex m_connectionMap_mtx; //! For thread safe access to the synchroneous connection map + MySQLConnection* m_bundle_conn; //! Bundled connection (see Database.ThreadBundleMask config) + AtomicUInt m_connections; //! Counter of MySQL connections; + std::string m_infoString; //! Infostring that is passed on to child connections. + TransactionQueues m_tranQueues; //! Transaction queues from diff. threads + ACE_Thread_Mutex m_transQueues_mtx; //! To guard m_transQueues + QueryQueues m_queryQueues; //! Query queues from diff threads +}; + +#endif
\ No newline at end of file diff --git a/src/server/shared/Database/MySQLConnection.cpp b/src/server/shared/Database/MySQLConnection.cpp new file mode 100644 index 00000000000..cd28474c63d --- /dev/null +++ b/src/server/shared/Database/MySQLConnection.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "MySQLConnection.h" +#include "DatabaseWorker.h" +#include "Utilities/Util.h" +#include "Utilities/Timer.h" + +MySQLConnection::MySQLConnection() : +m_Mysql(NULL) +{ +} + +MySQLConnection::MySQLConnection(ACE_Activation_Queue* queue) : +m_queue(queue), +m_Mysql(NULL) +{ + m_worker = new DatabaseWorker(m_queue, this); +} + +MySQLConnection::~MySQLConnection() +{ + delete m_worker; +} + +bool MySQLConnection::Open(const std::string& infoString) +{ + MYSQL *mysqlInit; + mysqlInit = mysql_init(NULL); + if (!mysqlInit) + { + sLog.outError("Could not initialize Mysql connection"); + return false; + } + + Tokens tokens = StrSplit(infoString, ";"); + + Tokens::iterator iter; + + std::string host, port_or_socket, user, password, database; + int port; + char const* unix_socket; + + iter = tokens.begin(); + + if (iter != tokens.end()) + host = *iter++; + if (iter != tokens.end()) + port_or_socket = *iter++; + if (iter != tokens.end()) + user = *iter++; + if (iter != tokens.end()) + password = *iter++; + if (iter != tokens.end()) + database = *iter++; + + mysql_options(mysqlInit, MYSQL_SET_CHARSET_NAME, "utf8"); + #ifdef _WIN32 + if (host==".") // named pipe use option (Windows) + { + unsigned int opt = MYSQL_PROTOCOL_PIPE; + mysql_options(mysqlInit, MYSQL_OPT_PROTOCOL, (char const*)&opt); + port = 0; + unix_socket = 0; + } + else // generic case + { + port = atoi(port_or_socket.c_str()); + unix_socket = 0; + } + #else + if (host==".") // socket use option (Unix/Linux) + { + unsigned int opt = MYSQL_PROTOCOL_SOCKET; + mysql_options(mysqlInit, MYSQL_OPT_PROTOCOL, (char const*)&opt); + host = "localhost"; + port = 0; + unix_socket = port_or_socket.c_str(); + } + else // generic case + { + port = atoi(port_or_socket.c_str()); + unix_socket = 0; + } + #endif + + m_Mysql = mysql_real_connect(mysqlInit, host.c_str(), user.c_str(), + password.c_str(), database.c_str(), port, unix_socket, 0); + + if (m_Mysql) + { + sLog.outDetail("Connected to MySQL database at %s", host.c_str()); + sLog.outString("MySQL client library: %s", mysql_get_client_info()); + sLog.outString("MySQL server ver: %s ", mysql_get_server_info( m_Mysql)); + + if (!mysql_autocommit(m_Mysql, 1)) + sLog.outDetail("AUTOCOMMIT SUCCESSFULLY SET TO 1"); + else + sLog.outDetail("AUTOCOMMIT NOT SET TO 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 + Execute("SET NAMES `utf8`"); + Execute("SET CHARACTER SET `utf8`"); + + #if MYSQL_VERSION_ID >= 50003 + my_bool my_true = (my_bool)1; + if (mysql_options(m_Mysql, MYSQL_OPT_RECONNECT, &my_true)) + sLog.outDetail("Failed to turn on MYSQL_OPT_RECONNECT."); + else + sLog.outDetail("Successfully turned on MYSQL_OPT_RECONNECT."); + #else + #warning "Your mySQL client lib version does not support reconnecting after a timeout.\nIf this causes you any trouble we advice you to upgrade your mySQL client libs to at least mySQL 5.0.13 to resolve this problem." + #endif + return true; + } + else + { + sLog.outError("Could not connect to MySQL database at %s: %s\n", host.c_str(), mysql_error(mysqlInit)); + mysql_close(mysqlInit); + return false; + } +} + +bool MySQLConnection::Execute(const char* sql) +{ + if (!m_Mysql) + return false; + + { + // guarded block for thread-safe mySQL request + ACE_Guard<ACE_Thread_Mutex> query_connection_guard(m_Mutex); + + #ifdef TRINITY_DEBUG + uint32 _s = getMSTime(); + #endif + if (mysql_query(m_Mysql, sql)) + { + sLog.outErrorDb("SQL: %s", sql); + sLog.outErrorDb("SQL ERROR: %s", mysql_error(m_Mysql)); + return false; + } + else + { + #ifdef TRINITY_DEBUG + sLog.outDebug("[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql); + #endif + } + } + + return true; +} + +QueryResult_AutoPtr MySQLConnection::Query(const char* sql) +{ + if (!sql) + return QueryResult_AutoPtr(NULL); + + MYSQL_RES *result = NULL; + MYSQL_FIELD *fields = NULL; + uint64 rowCount = 0; + uint32 fieldCount = 0; + + if (!_Query(sql, &result, &fields, &rowCount, &fieldCount)) + return QueryResult_AutoPtr(NULL); + + QueryResult *queryResult = new QueryResult(result, fields, rowCount, fieldCount); + + queryResult->NextRow(); + + return QueryResult_AutoPtr(queryResult); +} + +bool MySQLConnection::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount) +{ + if (!m_Mysql) + return false; + + { + // guarded block for thread-safe mySQL request + ACE_Guard<ACE_Thread_Mutex> query_connection_guard(m_Mutex); + #ifdef TRINITY_DEBUG + uint32 _s = getMSTime(); + #endif + if (mysql_query(m_Mysql, sql)) + { + sLog.outErrorDb("SQL: %s", sql); + sLog.outErrorDb("query ERROR: %s", mysql_error(m_Mysql)); + return false; + } + else + { + #ifdef TRINITY_DEBUG + sLog.outDebug("[%u ms] SQL: %s", getMSTimeDiff(_s,getMSTime()), sql); + #endif + } + + *pResult = mysql_store_result(m_Mysql); + *pRowCount = mysql_affected_rows(m_Mysql); + *pFieldCount = mysql_field_count(m_Mysql); + } + + if (!*pResult ) + return false; + + if (!*pRowCount) + { + mysql_free_result(*pResult); + return false; + } + + *pFields = mysql_fetch_fields(*pResult); + return true; +} + +void MySQLConnection::BeginTransaction() +{ + Execute("START TRANSACTION"); +} + +void MySQLConnection::RollbackTransaction() +{ + Execute("ROLLBACK"); +} + +void MySQLConnection::CommitTransaction() +{ + Execute("COMMIT"); +}
\ No newline at end of file diff --git a/src/server/shared/Database/MySQLConnection.h b/src/server/shared/Database/MySQLConnection.h new file mode 100644 index 00000000000..08ceaa2860c --- /dev/null +++ b/src/server/shared/Database/MySQLConnection.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MYSQLCONNECTION_H +#define _MYSQLCONNECTION_H + +class DatabaseWorker; + +class MySQLConnection +{ + friend class DatabaseWorkerPool; + + public: + MySQLConnection(); //! Constructor for synchroneous connections. + MySQLConnection(ACE_Activation_Queue* queue); //! Constructor for asynchroneous connections. + ~MySQLConnection(); + + bool Open(const std::string& infoString); //! Connection details. + + public: + bool Execute(const char* sql); + QueryResult_AutoPtr Query(const char* sql); + bool _Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount); + + void BeginTransaction(); + void RollbackTransaction(); + void CommitTransaction(); + + operator bool () const { return m_Mysql != NULL; } + + protected: + MYSQL* GetHandle() { return m_Mysql; } + + private: + ACE_Activation_Queue* m_queue; //! Queue shared with other asynchroneous connections. + DatabaseWorker* m_worker; //! Core worker task. + MYSQL * m_Mysql; //! MySQL Handle. + ACE_Thread_Mutex m_Mutex; +}; + +#endif
\ No newline at end of file diff --git a/src/server/shared/Database/MySQLThreading.h b/src/server/shared/Database/MySQLThreading.h new file mode 100644 index 00000000000..3c039a4d165 --- /dev/null +++ b/src/server/shared/Database/MySQLThreading.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _MYSQLTHREADING_H +#define _MYSQLTHREADING_H + +#include "Log.h" + +class MySQL +{ + public: + /*! Create a thread on the MySQL server to mirrior the calling thread, + initializes thread-specific variables and allows thread-specific + operations without concurrence from other threads. + This should only be called if multiple core threads are running + on the same MySQL connection. Seperate MySQL connections implicitly + create a mirror thread. + */ + static void Thread_Init() + { + mysql_thread_init(); + printf("Core thread with ID ["UI64FMTD"] initializing MySQL thread.", + (uint64)ACE_Based::Thread::currentId()); + } + + /*! Shuts down MySQL thread and frees resources, should only be called + when we terminate. MySQL threads and connections are not configurable + during runtime. + */ + static void Thread_End() + { + mysql_thread_end(); + printf("Core thread with ID ["UI64FMTD"] shutting down MySQL thread.", + (uint64)ACE_Based::Thread::currentId()); + } +}; + +#endif
\ No newline at end of file diff --git a/src/server/shared/Database/PreparedStatements.cpp b/src/server/shared/Database/PreparedStatements.cpp deleted file mode 100644 index ec57a0f90e8..00000000000 --- a/src/server/shared/Database/PreparedStatements.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "PreparedStatements.h" - -void PreparedStatementHolder::_prepareStatement(const char* name, const char* sql, Database *db, uint32 &count) -{ - const char prefix[] = "PREPARE "; - size_t querySize = 8 + strlen(name) + 6 + strlen(sql) + 2 + 1; - char* query = new char[querySize]; - strcpy(query, prefix); - strcat(query, name); - strcat(query, " FROM "); - strcat(query, "'"); - strcat(query, sql); - strcat(query, "'"); - - DEBUG_LOG("Preparing statement: %s", query); - db->Execute(query); - - delete[] query; - ++count; -} - -void PreparedStatementHolder::LoadAuthserver(Database *db, uint32 &count) -{ - _prepareStatement("auth_ping", "SELECT 1 FROM realmlist LIMIT 1", db, count); -}; - -void PreparedStatementHolder::Execute(Database *db, const char *name) -{ - const char prefix[] = "EXECUTE "; - size_t querySize = 8 + strlen(name) + 1; - char* query = new char[querySize]; - strcpy(query, prefix); - strcat(query, name); - - DEBUG_LOG("Prepared statement: %s", query); - db->Execute(query); - delete[] query; -} - -void PreparedStatementHolder::PExecute(Database *db, const char *name, const char* args) -{ - // NOTE: if args == NULL, we're crashing here. No need to waste performance on checking; - // devs must make sure they use PExecute for args and Execute for no args. - - const char prefix[] = "EXECUTE "; - size_t querySize = 8 + strlen(name) + 7 + strlen(args) + 1; - char* query = new char[querySize]; - strcpy(query, prefix); - strcat(query, name); - strcat(query, " USING "); - strcat(query, args); - - DEBUG_LOG("Prepared statement (parsed args): %s", query); - db->Execute(query); - delete[] query; -} - -QueryResult_AutoPtr PreparedStatementHolder::Query(Database *db, const char *name) -{ - QueryResult_AutoPtr _return = QueryResult_AutoPtr(NULL); - - const char prefix[] = "EXECUTE "; - size_t querySize = 8 + strlen(name) + 1; - char* query = new char[querySize]; - strcpy(query, prefix); - strcat(query, name); - - DEBUG_LOG("Prepared statement with resultset: %s", query); - _return = db->Query(query); - delete[] query; - return _return; -} - -QueryResult_AutoPtr PreparedStatementHolder::PQuery(Database *db, const char *name, const char *args) -{ - // NOTE: if args == NULL, we're crashing here. No need to waste performance on checking; - // devs must make sure they use PQuery for args and Query for no args. - - QueryResult_AutoPtr _return = QueryResult_AutoPtr(NULL); - - const char prefix[] = "EXECUTE "; - size_t querySize = 8 + strlen(name) + 7 + strlen(args) + 1; - char* query = new char[querySize]; - strcpy(query, prefix); - strcat(query, name); - strcat(query, " USING "); - strcat(query, args); - - DEBUG_LOG("Prepared statement with resultset (parsed args): %s", query); - _return = db->Query(query); - delete[] query; - return _return; -}
\ No newline at end of file diff --git a/src/server/shared/Database/PreparedStatements.h b/src/server/shared/Database/PreparedStatements.h deleted file mode 100644 index 277d2b833ec..00000000000 --- a/src/server/shared/Database/PreparedStatements.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef sPreparedStatement - -#include "ace/Singleton.h" -#include "Database/DatabaseEnv.h" - -class PreparedStatementHolder -{ - public: - ///- Load prepare statements on database $db and increase $count for every statement - void LoadCharacters(Database *db, uint32 &count); - void LoadAuthserver(Database *db, uint32 &count); - void LoadWorldserver(Database *db, uint32 &count); - - ///- Executes prepared statement that doesn't require feedback with name $name on database $db - void Execute(Database *db, const char* name); - ///- Executes prepared statement that doesn't require feedback with name $name and args $args - ///- on database $db - void PExecute(Database *db, const char* name, const char* args); - - ///- Executes a prepared statement without args on db $db with name $name and puts the result set in a pointer. - QueryResult_AutoPtr Query(Database* db, const char* name); - ///- Executes a prepared statement with args $args on db $db with name $name and put the result set in a pointer. - QueryResult_AutoPtr PQuery(Database* db, const char* name, const char* args); - - private: - void _prepareStatement(const char* name, const char* sql, Database *db, uint32 &count); - -}; -#define sPreparedStatement (*ACE_Singleton<PreparedStatementHolder, ACE_Null_Mutex>::instance()) -#endif
\ No newline at end of file diff --git a/src/server/shared/Database/SqlOperations.cpp b/src/server/shared/Database/SQLOperation.cpp index 33b96a30533..d3af5949faf 100644 --- a/src/server/shared/Database/SqlOperations.cpp +++ b/src/server/shared/Database/SQLOperation.cpp @@ -1,6 +1,4 @@ /* - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify @@ -18,71 +16,74 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "SqlOperations.h" -#include "SqlDelayThread.h" -#include "DatabaseEnv.h" -#include "DatabaseImpl.h" +#include "SQLOperation.h" +#include "MySQLConnection.h" -/// ---- ASYNC STATEMENTS / TRANSACTIONS ---- +/*! Basic, ad-hoc queries. */ +BasicStatementTask::BasicStatementTask(const char* sql) +{ + m_sql = strdup(sql); +} -void SqlStatement::Execute(Database *db) +BasicStatementTask::~BasicStatementTask() { - /// just do it - db->DirectExecute(m_sql); + free((void*)m_sql); } -void SqlTransaction::Execute(Database *db) +bool BasicStatementTask::Execute() { - const char* sql; + return m_conn->Execute(m_sql); +} + +/*! Transactions. */ +TransactionTask::TransactionTask() +{ +} + +TransactionTask::~TransactionTask() +{ + +} - m_Mutex.acquire(); - if (m_queue.empty()) +void TransactionTask::ForcefulDelete() +{ + while (!m_queries.empty()) { - m_Mutex.release(); - return; + free((void*)const_cast<char*>(m_queries.front())); + m_queries.pop(); } +} - db->DirectExecute("START TRANSACTION"); - while (!m_queue.empty()) - { - sql = m_queue.front(); +bool TransactionTask::Execute() +{ + if (m_queries.empty()) + return false; + + const char* sql; - if (!db->DirectExecute(sql)) + m_conn->BeginTransaction(); + while (!m_queries.empty()) + { + sql = m_queries.front(); + if (!m_conn->Execute(sql)) { free((void*)const_cast<char*>(sql)); - m_queue.pop(); - db->DirectExecute("ROLLBACK"); - while (!m_queue.empty()) - { - free((void*)const_cast<char*>(m_queue.front())); - m_queue.pop(); - } - m_Mutex.release(); - return; + m_queries.pop(); + m_conn->RollbackTransaction(); + ForcefulDelete(); + return false; } free((void*)const_cast<char*>(sql)); - m_queue.pop(); + m_queries.pop(); } - db->DirectExecute("COMMIT"); - m_Mutex.release(); -} - -/// ---- ASYNC QUERIES ---- - -void SqlQuery::Execute(Database *db) -{ - if (!m_callback || !m_queue) - return; - - /// execute the query and store the result in the callback - m_callback->SetResult(db->Query(m_sql)); - /// add the callback to the sql result queue of the thread it originated from - m_queue->add(m_callback); + m_conn->CommitTransaction(); + return true; } -void SqlResultQueue::Update() +/*! Callback statements/holders */ +void SQLResultQueue::Update() { /// execute the callbacks waiting in the synchronization queue Trinity::IQueryCallback* callback; @@ -93,39 +94,27 @@ void SqlResultQueue::Update() } } -bool SqlQueryHolder::Execute(Trinity::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue) -{ - if (!callback || !thread || !queue) - return false; - - /// delay the execution of the queries, sync them with the delay thread - /// which will in turn resync on execution (via the queue) and call back - SqlQueryHolderEx *holderEx = new SqlQueryHolderEx(this, callback, queue); - thread->Delay(holderEx); - return true; -} - -bool SqlQueryHolder::SetQuery(size_t index, const char *sql) +bool SQLQueryHolder::SetQuery(size_t index, const char *sql) { if (m_queries.size() <= index) { - sLog.outError("Query index (%u) out of range (size: %u) for query: %s",index,(uint32)m_queries.size(),sql); + sLog.outError("Query index (%u) out of range (size: %u) for query: %s", index, (uint32)m_queries.size(), sql); return false; } if (m_queries[index].first != NULL) { sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])", - index,m_queries[index].first,sql); + index, m_queries[index].first, sql); return false; } /// not executed yet, just stored (it's not called a holder for nothing) - m_queries[index] = SqlResultPair(strdup(sql), QueryResult_AutoPtr(NULL)); + m_queries[index] = SQLResultPair(strdup(sql), QueryResult_AutoPtr(NULL)); return true; } -bool SqlQueryHolder::SetPQuery(size_t index, const char *format, ...) +bool SQLQueryHolder::SetPQuery(size_t index, const char *format, ...) { if (!format) { @@ -145,10 +134,10 @@ bool SqlQueryHolder::SetPQuery(size_t index, const char *format, ...) return false; } - return SetQuery(index,szQuery); + return SetQuery(index, szQuery); } -QueryResult_AutoPtr SqlQueryHolder::GetResult(size_t index) +QueryResult_AutoPtr SQLQueryHolder::GetResult(size_t index) { if (index < m_queries.size()) { @@ -165,14 +154,14 @@ QueryResult_AutoPtr SqlQueryHolder::GetResult(size_t index) return QueryResult_AutoPtr(NULL); } -void SqlQueryHolder::SetResult(size_t index, QueryResult_AutoPtr result) +void SQLQueryHolder::SetResult(size_t index, QueryResult_AutoPtr result) { /// store the result in the holder if (index < m_queries.size()) m_queries[index].second = result; } -SqlQueryHolder::~SqlQueryHolder() +SQLQueryHolder::~SQLQueryHolder() { for (size_t i = 0; i < m_queries.size(); i++) { @@ -183,27 +172,41 @@ SqlQueryHolder::~SqlQueryHolder() } } -void SqlQueryHolder::SetSize(size_t size) +void SQLQueryHolder::SetSize(size_t size) { /// to optimize push_back, reserve the number of queries about to be executed m_queries.resize(size); } -void SqlQueryHolderEx::Execute(Database *db) +bool SQLQueryHolderTask::Execute() { if (!m_holder || !m_callback || !m_queue) - return; + return false; /// we can do this, we are friends - std::vector<SqlQueryHolder::SqlResultPair> &queries = m_holder->m_queries; + std::vector<SQLQueryHolder::SQLResultPair> &queries = m_holder->m_queries; for (size_t i = 0; i < queries.size(); i++) { /// execute all queries in the holder and pass the results char const *sql = queries[i].first; - if(sql) m_holder->SetResult(i, db->Query(sql)); + if (sql) + m_holder->SetResult(i, m_conn->Query(sql)); } /// sync with the caller thread m_queue->add(m_callback); + return true; } + +bool SQLQueryTask::Execute() +{ + if (!m_callback || !m_queue) + return false; + + /// execute the query and store the result in the callback + m_callback->SetResult(m_conn->Query(m_sql)); + /// add the callback to the sql result queue of the thread it originated from + m_queue->add(m_callback); + return true; +}
\ No newline at end of file diff --git a/src/server/shared/Database/SQLOperation.h b/src/server/shared/Database/SQLOperation.h new file mode 100644 index 00000000000..8f2a59151a3 --- /dev/null +++ b/src/server/shared/Database/SQLOperation.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _SQLOPERATION_H +#define _SQLOPERATION_H + +#include <ace/Method_Request.h> + +#include "Common.h" +#include "Threading/Callback.h" + +class MySQLConnection; + +class SQLOperation : public ACE_Method_Request +{ + public: + SQLOperation(){}; + int call() + { + Execute(); + return 0; + } + virtual bool Execute() = 0; + + virtual void SetConnection(MySQLConnection* con) { m_conn = con; } + + MySQLConnection* m_conn; +}; + +/*! Raw, ad-hoc query. */ +class BasicStatementTask : public SQLOperation +{ + public: + BasicStatementTask(const char* sql); + ~BasicStatementTask(); + + bool Execute(); + + private: + const char* m_sql; //- Raw query to be executed +}; + +/*! Transactions */ +class TransactionTask : public SQLOperation +{ + public: + TransactionTask(); + ~TransactionTask(); + void ForcefulDelete(); + + bool Execute(); + + private: + std::queue<char*> m_queries; +}; + +/*! ResultQueue */ +class SQLResultQueue : public ACE_Based::LockedQueue<Trinity::IQueryCallback* , ACE_Thread_Mutex> +{ + public: + SQLResultQueue() {} + void Update(); +}; + +class SQLQueryHolder +{ + friend class SQLQueryHolderTask; + private: + typedef std::pair<const char*, QueryResult_AutoPtr> SQLResultPair; + std::vector<SQLResultPair> m_queries; + public: + SQLQueryHolder() {} + ~SQLQueryHolder(); + bool SetQuery(size_t index, const char *sql); + bool SetPQuery(size_t index, const char *format, ...) ATTR_PRINTF(3,4); + void SetSize(size_t size); + QueryResult_AutoPtr GetResult(size_t index); + void SetResult(size_t index, QueryResult_AutoPtr result); +}; + +class SQLQueryHolderTask : public SQLOperation +{ + private: + SQLQueryHolder * m_holder; + Trinity::IQueryCallback * m_callback; + SQLResultQueue * m_queue; + public: + SQLQueryHolderTask(SQLQueryHolder *holder, Trinity::IQueryCallback * callback, SQLResultQueue * queue) + : m_holder(holder), m_callback(callback), m_queue(queue) {} + bool Execute(); +}; + +class SQLQueryTask : public SQLOperation +{ + private: + const char *m_sql; + Trinity::IQueryCallback * m_callback; + SQLResultQueue * m_queue; + public: + SQLQueryTask(const char *sql, Trinity::IQueryCallback * callback, SQLResultQueue * queue) + : m_sql(strdup(sql)), m_callback(callback), m_queue(queue) {} + ~SQLQueryTask() { void* tofree = const_cast<char*>(m_sql); free(tofree); } + bool Execute(); +}; + + +#endif
\ No newline at end of file diff --git a/src/server/shared/Database/SQLStorage.cpp b/src/server/shared/Database/SQLStorage.cpp index 1a65824a631..26aecb80fa3 100644 --- a/src/server/shared/Database/SQLStorage.cpp +++ b/src/server/shared/Database/SQLStorage.cpp @@ -21,7 +21,7 @@ #include "SQLStorage.h" #include "SQLStorageImpl.h" -extern Database WorldDatabase; +extern DatabaseType WorldDatabase; const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiifffliiiiiiiliiisi"; const char CreatureInfodstfmt[]="iiiiiiiiiisssibbiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiifffliiiiiiiliiiii"; diff --git a/src/server/shared/Database/SqlOperations.h b/src/server/shared/Database/SqlOperations.h deleted file mode 100644 index 337790e4c72..00000000000 --- a/src/server/shared/Database/SqlOperations.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> - * - * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __SQLOPERATIONS_H -#define __SQLOPERATIONS_H - -#include "Common.h" - -#include "ace/Thread_Mutex.h" -#include "ace/Method_Request.h" -#include "Threading/LockedQueue.h" -#include <queue> -#include "Threading/Callback.h" -#include "QueryResult.h" - -/// ---- BASE --- - -class Database; -class SqlDelayThread; - -class SqlOperation -{ - public: - virtual void OnRemove() { delete this; } - virtual void Execute(Database *db) = 0; - virtual ~SqlOperation() {} -}; - -/// ---- ASYNC STATEMENTS / TRANSACTIONS ---- - -class SqlStatement : public SqlOperation -{ - private: - const char *m_sql; - public: - SqlStatement(const char *sql) : m_sql(strdup(sql)){} - ~SqlStatement() { void* tofree = const_cast<char*>(m_sql); free(tofree); } - void Execute(Database *db); -}; - -class SqlTransaction : public SqlOperation -{ - private: - std::queue<const char*> m_queue; - ACE_Thread_Mutex m_Mutex; - public: - SqlTransaction() {} - void DelayExecute(const char *sql) - { - m_Mutex.acquire(); - char* _sql = strdup(sql); - if (_sql) - m_queue.push(_sql); - m_Mutex.release(); - } - void Execute(Database *db); -}; - -/// ---- ASYNC QUERIES ---- - -class SqlQuery; /// contains a single async query -class QueryResult; /// the result of one -class SqlResultQueue; /// queue for thread sync -class SqlQueryHolder; /// groups several async quries -class SqlQueryHolderEx; /// points to a holder, added to the delay thread - -class SqlResultQueue : public ACE_Based::LockedQueue<Trinity::IQueryCallback* , ACE_Thread_Mutex> -{ - public: - SqlResultQueue() {} - void Update(); -}; - -class SqlQuery : public SqlOperation -{ - private: - const char *m_sql; - Trinity::IQueryCallback * m_callback; - SqlResultQueue * m_queue; - public: - SqlQuery(const char *sql, Trinity::IQueryCallback * callback, SqlResultQueue * queue) - : m_sql(strdup(sql)), m_callback(callback), m_queue(queue) {} - ~SqlQuery() { void* tofree = const_cast<char*>(m_sql); free(tofree); } - void Execute(Database *db); -}; - -class SqlQueryHolder -{ - friend class SqlQueryHolderEx; - private: - typedef std::pair<const char*, QueryResult_AutoPtr> SqlResultPair; - std::vector<SqlResultPair> m_queries; - public: - SqlQueryHolder() {} - ~SqlQueryHolder(); - bool SetQuery(size_t index, const char *sql); - bool SetPQuery(size_t index, const char *format, ...) ATTR_PRINTF(3,4); - void SetSize(size_t size); - QueryResult_AutoPtr GetResult(size_t index); - void SetResult(size_t index, QueryResult_AutoPtr result); - bool Execute(Trinity::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue); -}; - -class SqlQueryHolderEx : public SqlOperation -{ - private: - SqlQueryHolder * m_holder; - Trinity::IQueryCallback * m_callback; - SqlResultQueue * m_queue; - public: - SqlQueryHolderEx(SqlQueryHolder *holder, Trinity::IQueryCallback * callback, SqlResultQueue * queue) - : m_holder(holder), m_callback(callback), m_queue(queue) {} - void Execute(Database *db); -}; - -class SqlAsyncTask : public ACE_Method_Request -{ -public: - SqlAsyncTask(Database * db, SqlOperation * op) : m_db(db), m_op(op){} - ~SqlAsyncTask() - { - if (!m_op) - return; - - delete m_op; - m_op = NULL; - } - - int call() - { - if (m_db == NULL || m_op == NULL) - return -1; - - try - { - m_op->Execute(m_db); - } - catch(...) - { - return -1; - } - - return 0; - } - -private: - Database * m_db; - SqlOperation * m_op; -}; -#endif //__SQLOPERATIONS_H - |