From b8a1ffcf5022477402cea9bfee2b9ddcd830513e Mon Sep 17 00:00:00 2001 From: raczman Date: Thu, 25 Jun 2009 15:56:45 +0200 Subject: Implemented separate connection for SqlDelayThread This should result in less locking when accessing database, and improved performance. * Changed SqlDelay queue type to monitored queue, and removed 10ms check period. thanks to Derex, mknjc, Jeniczek and Christyan for ideas and tests. --HG-- branch : trunk --- src/shared/Database/Database.h | 2 +- src/shared/Database/DatabaseMysql.cpp | 10 +++++----- src/shared/Database/DatabaseMysql.h | 4 ++-- src/shared/Database/MySQLDelayThread.h | 2 +- src/shared/Database/SqlDelayThread.cpp | 27 +++++++++++++++++---------- src/shared/Database/SqlDelayThread.h | 8 +++++--- 6 files changed, 31 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index c2ee9349979..6efd5536725 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -50,7 +50,7 @@ class TRINITY_DLL_SPEC Database virtual ~Database(); virtual bool Initialize(const char *infoString); - virtual void InitDelayThread() = 0; + virtual void InitDelayThread(const char *infoString) = 0; virtual void HaltDelayThread() = 0; virtual QueryResult* Query(const char *sql) = 0; diff --git a/src/shared/Database/DatabaseMysql.cpp b/src/shared/Database/DatabaseMysql.cpp index 77a59a69c57..19c96422f18 100644 --- a/src/shared/Database/DatabaseMysql.cpp +++ b/src/shared/Database/DatabaseMysql.cpp @@ -70,7 +70,7 @@ DatabaseMysql::~DatabaseMysql() mysql_library_end(); } -bool DatabaseMysql::Initialize(const char *infoString) +bool DatabaseMysql::Initialize(const char *infoString, bool initDelayThread) { if(!Database::Initialize(infoString)) @@ -84,8 +84,8 @@ bool DatabaseMysql::Initialize(const char *infoString) sLog.outError( "Could not initialize Mysql connection" ); return false; } - - InitDelayThread(); + if(initDelayThread) + InitDelayThread(infoString); Tokens tokens = StrSplit(infoString, ";"); @@ -403,12 +403,12 @@ unsigned long DatabaseMysql::escape_string(char *to, const char *from, unsigned return(mysql_real_escape_string(mMysql, to, from, length)); } -void DatabaseMysql::InitDelayThread() +void DatabaseMysql::InitDelayThread(const char* infoString) { assert(!m_delayThread); //New delay thread for delay execute - m_delayThread = new ZThread::Thread(m_threadBody = new MySQLDelayThread(this)); + m_delayThread = new ZThread::Thread(m_threadBody = new MySQLDelayThread(this,infoString)); } void DatabaseMysql::HaltDelayThread() diff --git a/src/shared/Database/DatabaseMysql.h b/src/shared/Database/DatabaseMysql.h index 1826a08f2aa..2dee259193e 100644 --- a/src/shared/Database/DatabaseMysql.h +++ b/src/shared/Database/DatabaseMysql.h @@ -45,8 +45,8 @@ class TRINITY_DLL_SPEC DatabaseMysql : public Database //! Initializes Mysql and connects to a server. /*! infoString should be formated like hostname;username;password;database. */ - bool Initialize(const char *infoString); - void InitDelayThread(); + bool Initialize(const char *infoString, bool initDelayThread = true); + void InitDelayThread(const char* infoString); void HaltDelayThread(); QueryResult* Query(const char *sql); bool Execute(const char *sql); diff --git a/src/shared/Database/MySQLDelayThread.h b/src/shared/Database/MySQLDelayThread.h index 14cf1a64617..74885236f28 100644 --- a/src/shared/Database/MySQLDelayThread.h +++ b/src/shared/Database/MySQLDelayThread.h @@ -26,7 +26,7 @@ class MySQLDelayThread : public SqlDelayThread { public: - MySQLDelayThread(Database* db) : SqlDelayThread(db) {} + MySQLDelayThread(Database* db,const char* infoString) : SqlDelayThread(db, infoString) {} void Stop() { SqlDelayThread::Stop(); } }; #endif //__MYSQLDELAYTHREAD_H diff --git a/src/shared/Database/SqlDelayThread.cpp b/src/shared/Database/SqlDelayThread.cpp index 16d5146fc53..612cf55121b 100644 --- a/src/shared/Database/SqlDelayThread.cpp +++ b/src/shared/Database/SqlDelayThread.cpp @@ -22,8 +22,12 @@ #include "Database/SqlOperations.h" #include "DatabaseEnv.h" -SqlDelayThread::SqlDelayThread(Database* db) : m_dbEngine(db), m_running(true) +SqlDelayThread::SqlDelayThread(Database* db, const char* infoString) :m_running(true) { + + m_dbEngine = new DatabaseType; + ((DatabaseType*)m_dbEngine)->Initialize(infoString, false); + } void SqlDelayThread::run() @@ -35,15 +39,17 @@ void SqlDelayThread::run() while (m_running) { - // if the running state gets turned off while sleeping - // empty the queue before exiting - ZThread::Thread::sleep(10); - while (!m_sqlQueue.empty()) - { - s = m_sqlQueue.next(); - s->Execute(m_dbEngine); - delete s; - } + try + { + s = m_sqlQueue.next(); + } + catch(...) + {continue;} + if(!s) + continue; + s->Execute(m_dbEngine); + delete s; + } #ifndef DO_POSTGRESQL @@ -54,5 +60,6 @@ void SqlDelayThread::run() void SqlDelayThread::Stop() { m_running = false; + m_sqlQueue.cancel(); } diff --git a/src/shared/Database/SqlDelayThread.h b/src/shared/Database/SqlDelayThread.h index 4c77c122f1e..7f534d93237 100644 --- a/src/shared/Database/SqlDelayThread.h +++ b/src/shared/Database/SqlDelayThread.h @@ -24,14 +24,16 @@ #include "zthread/Thread.h" #include "zthread/Runnable.h" #include "zthread/FastMutex.h" -#include "zthread/LockedQueue.h" +#include "zthread/MonitoredQueue.h" class Database; class SqlOperation; + + class SqlDelayThread : public ZThread::Runnable { - typedef ZThread::LockedQueue SqlQueue; +typedef ZThread::MonitoredQueue SqlQueue; private: SqlQueue m_sqlQueue; ///< Queue of SQL statements Database* m_dbEngine; ///< Pointer to used Database engine @@ -39,7 +41,7 @@ class SqlDelayThread : public ZThread::Runnable SqlDelayThread(); public: - SqlDelayThread(Database* db); + SqlDelayThread(Database* db,const char* infoString); ///< Put sql statement to delay queue inline bool Delay(SqlOperation* sql) { m_sqlQueue.add(sql); return true; } -- cgit v1.2.3 From 8334693fe73f0d63f0738028a5a2365554ea97b3 Mon Sep 17 00:00:00 2001 From: krz Date: Thu, 25 Jun 2009 17:14:56 +0200 Subject: Backported from TC2: *Fix typo causing problems with buying items. --HG-- branch : trunk --- src/game/Player.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 7e400be4cb0..525e1448ce8 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17131,9 +17131,9 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint { // cheating attempt if(count < 1) count = 1; - + // cheating attempt - if(slot > MAX_BAG_SIZE) + if(slot > MAX_BAG_SIZE && slot != NULL_SLOT) return false; if(!isAlive()) -- cgit v1.2.3 From a494b0436c5bdcbcff4d89c7bdd63060fd09133b Mon Sep 17 00:00:00 2001 From: krz Date: Fri, 26 Jun 2009 18:20:42 +0200 Subject: Fix exploit in BuyItemFromVendor --HG-- branch : trunk --- src/game/Player.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 525e1448ce8..54e35a28466 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17145,6 +17145,15 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint SendBuyError( BUY_ERR_CANT_FIND_ITEM, NULL, item, 0); return false; } + else + { + if(slot > pProto->ContainerSlots) + { + sLog.outDebug("CHEATING ATTEMPT slot > pProto->ContainerSlots in BuyItemFromVendor playerGUID: "I64FMT" name: %s slot: %u", GetGUID(), GetName(), slot); + return false; + } + } + Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*this, vendorguid,UNIT_NPC_FLAG_VENDOR); if (!pCreature) -- cgit v1.2.3 From 10ac2b73b88d84bd3005da69b145255a9f3aa2b9 Mon Sep 17 00:00:00 2001 From: krz Date: Fri, 26 Jun 2009 20:58:39 +0200 Subject: Better check to prevent exploiting in BuyItemFromVendor --HG-- branch : trunk --- src/game/Player.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/game/Player.cpp b/src/game/Player.cpp index 54e35a28466..4c651ca8e89 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -17145,15 +17145,6 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint SendBuyError( BUY_ERR_CANT_FIND_ITEM, NULL, item, 0); return false; } - else - { - if(slot > pProto->ContainerSlots) - { - sLog.outDebug("CHEATING ATTEMPT slot > pProto->ContainerSlots in BuyItemFromVendor playerGUID: "I64FMT" name: %s slot: %u", GetGUID(), GetName(), slot); - return false; - } - } - Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*this, vendorguid,UNIT_NPC_FLAG_VENDOR); if (!pCreature) @@ -17266,6 +17257,12 @@ bool Player::BuyItemFromVendor(uint64 vendorguid, uint32 item, uint8 count, uint { if( bagguid == pBag->GetGUID() ) { + // slot is counted from 0 but BagSize from 1 + if(slot+1 > pBag->GetBagSize()) + { + sLog.outDebug("CHEATING ATTEMPT slot > bagSize in BuyItemFromVendor playerGUID: "I64FMT" name: %s slot: %u", GetGUID(), GetName(), slot); + return false; + } bag = i; break; } -- cgit v1.2.3