diff --git a/dep/include/mersennetwister/MersenneTwister.h b/dep/include/mersennetwister/MersenneTwister.h index af91931..ab8d94c 100644 --- a/dep/include/mersennetwister/MersenneTwister.h +++ b/dep/include/mersennetwister/MersenneTwister.h @@ -70,69 +70,69 @@ class MTRand { // Data public: typedef ::uint32 uint32; - enum { N = 624 }; // length of state vector - enum { SAVE = N + 1 }; // length of array for save() + enum { N = 624 }; // length of state vector + enum { SAVE = N + 1 }; // length of array for save() protected: - enum { M = 397 }; // period parameter - - uint32 state[N]; // internal state - uint32 *pNext; // next value to get from state - int left; // number of values left before reload needed + enum { M = 397 }; // period parameter + + uint32 state[N]; // internal state + uint32 *pNext; // next value to get from state + int left; // number of values left before reload needed //Methods public: - MTRand( const uint32& oneSeed ); // initialize with a simple uint32 - MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array - MTRand(); // auto-initialize with /dev/urandom or time() and clock() - MTRand(const MTRand&); // prevent copy constructor - MTRand& operator=(const MTRand&); // no-op operator= - - // Do NOT use for CRYPTOGRAPHY without securely hashing several returned - // values together, otherwise the generator state can be learned after - // reading 624 consecutive values. - - // Access to 32-bit random numbers - double rand(); // real number in [0,1] - double rand( const double& n ); // real number in [0,n] - double randExc(); // real number in [0,1) - double randExc( const double& n ); // real number in [0,n) - double randDblExc(); // real number in (0,1) - double randDblExc( const double& n ); // real number in (0,n) - uint32 randInt(); // integer in [0,2^32-1] - uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32 - double operator()() { return rand(); } // same as rand() - - // Access to 53-bit random numbers (capacity of IEEE double precision) - double rand53(); // real number in [0,1) - - // Access to nonuniform random number distributions - double randNorm( const double& mean = 0.0, const double& variance = 0.0 ); - - // Re-seeding functions with same behavior as initializers - void seed( const uint32 oneSeed ); - void seed( uint32 *const bigSeed, const uint32 seedLength = N ); - void seed(); - - // Saving and loading generator state - void save( uint32* saveArray ) const; // to array of size SAVE - void load( uint32 *const loadArray ); // from such array + MTRand( const uint32& oneSeed ); // initialize with a simple uint32 + MTRand( uint32 *const bigSeed, uint32 const seedLength = N ); // or an array + MTRand(); // auto-initialize with /dev/urandom or time() and clock() + MTRand(const MTRand&); // prevent copy constructor + MTRand& operator=(const MTRand&); // no-op operator= + + // Do NOT use for CRYPTOGRAPHY without securely hashing several returned + // values together, otherwise the generator state can be learned after + // reading 624 consecutive values. + + // Access to 32-bit random numbers + double rand(); // real number in [0,1] + double rand( const double& n ); // real number in [0,n] + double randExc(); // real number in [0,1) + double randExc( const double& n ); // real number in [0,n) + double randDblExc(); // real number in (0,1) + double randDblExc( const double& n ); // real number in (0,n) + uint32 randInt(); // integer in [0,2^32-1] + uint32 randInt( const uint32& n ); // integer in [0,n] for n < 2^32 + double operator()() { return rand(); } // same as rand() + + // Access to 53-bit random numbers (capacity of IEEE double precision) + double rand53(); // real number in [0,1) + + // Access to nonuniform random number distributions + double randNorm( const double& mean = 0.0, const double& variance = 0.0 ); + + // Re-seeding functions with same behavior as initializers + void seed( const uint32 oneSeed ); + void seed( uint32 *const bigSeed, const uint32 seedLength = N ); + void seed(); + + // Saving and loading generator state + void save( uint32* saveArray ) const; // to array of size SAVE + void load( uint32 *const loadArray ); // from such array /* Mangos not use streams for random values output - friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand ); - friend std::istream& operator>>( std::istream& is, MTRand& mtrand ); + friend std::ostream& operator<<( std::ostream& os, const MTRand& mtrand ); + friend std::istream& operator>>( std::istream& is, MTRand& mtrand ); */ protected: - void initialize( const uint32 oneSeed ); - void reload(); - uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; } - uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; } - uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; } - uint32 mixBits( const uint32& u, const uint32& v ) const - { return hiBit(u) | loBits(v); } - uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const - { return m ^ (mixBits(s0,s1)>>1) ^ uint32(-(int32)(loBit(s1) & 0x9908b0dfUL)); } - static uint32 hash( time_t t, clock_t c ); + void initialize( const uint32 oneSeed ); + void reload(); + uint32 hiBit( const uint32& u ) const { return u & 0x80000000UL; } + uint32 loBit( const uint32& u ) const { return u & 0x00000001UL; } + uint32 loBits( const uint32& u ) const { return u & 0x7fffffffUL; } + uint32 mixBits( const uint32& u, const uint32& v ) const + { return hiBit(u) | loBits(v); } + uint32 twist( const uint32& m, const uint32& s0, const uint32& s1 ) const + { return m ^ (mixBits(s0,s1)>>1) ^ uint32(-(int32)(loBit(s1) & 0x9908b0dfUL)); } + static uint32 hash( time_t t, clock_t c ); }; inline MTRand::MTRand(const MTRand&) @@ -142,232 +142,232 @@ inline MTRand& MTRand::operator=(const MTRand&) { return *this; } inline MTRand::MTRand( const uint32& oneSeed ) - { seed(oneSeed); } + { seed(oneSeed); } inline MTRand::MTRand( uint32 *const bigSeed, const uint32 seedLength ) - { seed(bigSeed,seedLength); } + { seed(bigSeed,seedLength); } inline MTRand::MTRand() - { seed(); } + { seed(); } inline double MTRand::rand() - { return double(randInt()) * (1.0/4294967295.0); } + { return double(randInt()) * (1.0/4294967295.0); } inline double MTRand::rand( const double& n ) - { return rand() * n; } + { return rand() * n; } inline double MTRand::randExc() - { return double(randInt()) * (1.0/4294967296.0); } + { return double(randInt()) * (1.0/4294967296.0); } inline double MTRand::randExc( const double& n ) - { return randExc() * n; } + { return randExc() * n; } inline double MTRand::randDblExc() - { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); } + { return ( double(randInt()) + 0.5 ) * (1.0/4294967296.0); } inline double MTRand::randDblExc( const double& n ) - { return randDblExc() * n; } + { return randDblExc() * n; } inline double MTRand::rand53() { - uint32 a = randInt() >> 5, b = randInt() >> 6; - return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada + uint32 a = randInt() >> 5, b = randInt() >> 6; + return ( a * 67108864.0 + b ) * (1.0/9007199254740992.0); // by Isaku Wada } inline double MTRand::randNorm( const double& mean, const double& variance ) { - // Return a real number from a normal (Gaussian) distribution with given - // mean and variance by Box-Muller method - double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance; - double phi = 2.0 * 3.14159265358979323846264338328 * randExc(); - return mean + r * cos(phi); + // Return a real number from a normal (Gaussian) distribution with given + // mean and variance by Box-Muller method + double r = sqrt( -2.0 * log( 1.0-randDblExc()) ) * variance; + double phi = 2.0 * 3.14159265358979323846264338328 * randExc(); + return mean + r * cos(phi); } inline MTRand::uint32 MTRand::randInt() { - // Pull a 32-bit integer from the generator state - // Every other access function simply transforms the numbers extracted here - - if( left == 0 ) reload(); - --left; - - register uint32 s1; - s1 = *pNext++; - s1 ^= (s1 >> 11); - s1 ^= (s1 << 7) & 0x9d2c5680UL; - s1 ^= (s1 << 15) & 0xefc60000UL; - return ( s1 ^ (s1 >> 18) ); + // Pull a 32-bit integer from the generator state + // Every other access function simply transforms the numbers extracted here + + if( left == 0 ) reload(); + --left; + + register uint32 s1; + s1 = *pNext++; + s1 ^= (s1 >> 11); + s1 ^= (s1 << 7) & 0x9d2c5680UL; + s1 ^= (s1 << 15) & 0xefc60000UL; + return ( s1 ^ (s1 >> 18) ); } inline MTRand::uint32 MTRand::randInt( const uint32& n ) { - // Find which bits are used in n - // Optimized by Magnus Jonsson (magnus@smartelectronix.com) - uint32 used = n; - used |= used >> 1; - used |= used >> 2; - used |= used >> 4; - used |= used >> 8; - used |= used >> 16; - - // Draw numbers until one is found in [0,n] - uint32 i; - do - i = randInt() & used; // toss unused bits to shorten search - while( i > n ); - return i; + // Find which bits are used in n + // Optimized by Magnus Jonsson (magnus@smartelectronix.com) + uint32 used = n; + used |= used >> 1; + used |= used >> 2; + used |= used >> 4; + used |= used >> 8; + used |= used >> 16; + + // Draw numbers until one is found in [0,n] + uint32 i; + do + i = randInt() & used; // toss unused bits to shorten search + while( i > n ); + return i; } inline void MTRand::seed( const uint32 oneSeed ) { - // Seed the generator with a simple uint32 - initialize(oneSeed); - reload(); + // Seed the generator with a simple uint32 + initialize(oneSeed); + reload(); } inline void MTRand::seed( uint32 *const bigSeed, const uint32 seedLength ) { - // Seed the generator with an array of uint32's - // There are 2^19937-1 possible initial states. This function allows - // all of those to be accessed by providing at least 19937 bits (with a - // default seed length of N = 624 uint32's). Any bits above the lower 32 - // in each element are discarded. - // Just call seed() if you want to get array from /dev/urandom - initialize(19650218UL); - register int i = 1; - register uint32 j = 0; - register int k = ( N > seedLength ? N : seedLength ); - for( ; k; --k ) - { - state[i] = - state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL ); - state[i] += ( bigSeed[j] & 0xffffffffUL ) + j; - state[i] &= 0xffffffffUL; - ++i; ++j; - if( i >= N ) { state[0] = state[N-1]; i = 1; } - if( j >= seedLength ) j = 0; - } - for( k = N - 1; k; --k ) - { - state[i] = - state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL ); - state[i] -= i; - state[i] &= 0xffffffffUL; - ++i; - if( i >= N ) { state[0] = state[N-1]; i = 1; } - } - state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array - reload(); + // Seed the generator with an array of uint32's + // There are 2^19937-1 possible initial states. This function allows + // all of those to be accessed by providing at least 19937 bits (with a + // default seed length of N = 624 uint32's). Any bits above the lower 32 + // in each element are discarded. + // Just call seed() if you want to get array from /dev/urandom + initialize(19650218UL); + register int i = 1; + register uint32 j = 0; + register int k = ( N > seedLength ? N : seedLength ); + for( ; k; --k ) + { + state[i] = + state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1664525UL ); + state[i] += ( bigSeed[j] & 0xffffffffUL ) + j; + state[i] &= 0xffffffffUL; + ++i; ++j; + if( i >= N ) { state[0] = state[N-1]; i = 1; } + if( j >= seedLength ) j = 0; + } + for( k = N - 1; k; --k ) + { + state[i] = + state[i] ^ ( (state[i-1] ^ (state[i-1] >> 30)) * 1566083941UL ); + state[i] -= i; + state[i] &= 0xffffffffUL; + ++i; + if( i >= N ) { state[0] = state[N-1]; i = 1; } + } + state[0] = 0x80000000UL; // MSB is 1, assuring non-zero initial array + reload(); } inline void MTRand::seed() { - // Seed the generator with hash of time() and clock() values - seed( hash( time(NULL), clock() ) ); + // Seed the generator with hash of time() and clock() values + seed( hash( time(NULL), clock() ) ); } inline void MTRand::initialize( const uint32 seed ) { - // Initialize generator state with seed - // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. - // In previous versions, most significant bits (MSBs) of the seed affect - // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. - register uint32 *s = state; - register uint32 *r = state; - register int i = 1; - *s++ = seed & 0xffffffffUL; - for( ; i < N; ++i ) - { - *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL; - r++; - } + // Initialize generator state with seed + // See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. + // In previous versions, most significant bits (MSBs) of the seed affect + // only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. + register uint32 *s = state; + register uint32 *r = state; + register int i = 1; + *s++ = seed & 0xffffffffUL; + for( ; i < N; ++i ) + { + *s++ = ( 1812433253UL * ( *r ^ (*r >> 30) ) + i ) & 0xffffffffUL; + r++; + } } inline void MTRand::reload() { - // Generate N new values in state - // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) - register uint32 *p = state; - register int i; - for( i = N - M; i--; ++p ) - *p = twist( p[M], p[0], p[1] ); - for( i = M; --i; ++p ) - *p = twist( p[M-N], p[0], p[1] ); - *p = twist( p[M-N], p[0], state[0] ); - - left = N, pNext = state; + // Generate N new values in state + // Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) + register uint32 *p = state; + register int i; + for( i = N - M; i--; ++p ) + *p = twist( p[M], p[0], p[1] ); + for( i = M; --i; ++p ) + *p = twist( p[M-N], p[0], p[1] ); + *p = twist( p[M-N], p[0], state[0] ); + + left = N, pNext = state; } inline MTRand::uint32 MTRand::hash( time_t t, clock_t c ) { - // Get a uint32 from t and c - // Better than uint32(x) in case x is floating point in [0,1] - // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk) - - static uint32 differ = 0; // guarantee time-based seeds will change - - uint32 h1 = 0; - unsigned char *p = (unsigned char *) &t; - for( size_t i = 0; i < sizeof(t); ++i ) - { - h1 *= UCHAR_MAX + 2U; - h1 += p[i]; - } - uint32 h2 = 0; - p = (unsigned char *) &c; - for( size_t j = 0; j < sizeof(c); ++j ) - { - h2 *= UCHAR_MAX + 2U; - h2 += p[j]; - } - return ( h1 + differ++ ) ^ h2; + // Get a uint32 from t and c + // Better than uint32(x) in case x is floating point in [0,1] + // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk) + + static uint32 differ = 0; // guarantee time-based seeds will change + + uint32 h1 = 0; + unsigned char *p = (unsigned char *) &t; + for( size_t i = 0; i < sizeof(t); ++i ) + { + h1 *= UCHAR_MAX + 2U; + h1 += p[i]; + } + uint32 h2 = 0; + p = (unsigned char *) &c; + for( size_t j = 0; j < sizeof(c); ++j ) + { + h2 *= UCHAR_MAX + 2U; + h2 += p[j]; + } + return ( h1 + differ++ ) ^ h2; } inline void MTRand::save( uint32* saveArray ) const { - register uint32 *sa = saveArray; - register const uint32 *s = state; - register int i = N; - for( ; i--; *sa++ = *s++ ) {} - *sa = left; + register uint32 *sa = saveArray; + register const uint32 *s = state; + register int i = N; + for( ; i--; *sa++ = *s++ ) {} + *sa = left; } inline void MTRand::load( uint32 *const loadArray ) { - register uint32 *s = state; - register uint32 *la = loadArray; - register int i = N; - for( ; i--; *s++ = *la++ ) {} - left = *la; - pNext = &state[N-left]; + register uint32 *s = state; + register uint32 *la = loadArray; + register int i = N; + for( ; i--; *s++ = *la++ ) {} + left = *la; + pNext = &state[N-left]; } /* Mangos not use streams for random values output inline std::ostream& operator<<( std::ostream& os, const MTRand& mtrand ) { - register const MTRand::uint32 *s = mtrand.state; - register int i = mtrand.N; - for( ; i--; os << *s++ << "\t" ) {} - return os << mtrand.left; + register const MTRand::uint32 *s = mtrand.state; + register int i = mtrand.N; + for( ; i--; os << *s++ << "\t" ) {} + return os << mtrand.left; } inline std::istream& operator>>( std::istream& is, MTRand& mtrand ) { - register MTRand::uint32 *s = mtrand.state; - register int i = mtrand.N; - for( ; i--; is >> *s++ ) {} - is >> mtrand.left; - mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left]; - return is; + register MTRand::uint32 *s = mtrand.state; + register int i = mtrand.N; + for( ; i--; is >> *s++ ) {} + is >> mtrand.left; + mtrand.pNext = &mtrand.state[mtrand.N-mtrand.left]; + return is; } */ diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index ecde680..e1f0ad5 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -937,10 +937,14 @@ void WorldSession::HandleChangePlayerNameOpcode(WorldPacket& recv_data) CharacterDatabase.escape_string(newname); - CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, GUID_LOPART(guid), newname, "SELECT guid, at_login, name FROM characters WHERE guid = '%u' XOR name = '%s'", GUID_LOPART(guid), newname.c_str()); + CharacterDatabase.AsyncPQuery(&WorldSession::HandleChangePlayerNameOpcodeCallBack, + GetAccountId(), newname, GUID_LOPART(guid), + "SELECT NULL FROM characters WHERE guid = '%d' and account = '%d' and (at_login & 1) = 1 and not exists (SELECT NULL FROM characters WHERE name = 'Timoha2')", + GUID_LOPART(guid), newname.c_str() + ); } -void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uint32 accountId, std::string newname) +void WorldSession::HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uint32 accountId, std::string newname, uint32 guid_low) { WorldSession * session = sWorld.FindSession(accountId); if(!session) diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 7e20ad4..eca441f 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -542,7 +542,7 @@ class MANGOS_DLL_SPEC WorldSession void HandleSetActionBar(WorldPacket& recv_data); void HandleChangePlayerNameOpcode(WorldPacket& recv_data); - static void HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uint32 accountId, std::string newname); + static void HandleChangePlayerNameOpcodeCallBack(QueryResult *result, uint32 accountId, std::string newname, uint32 guid_low); void HandleDeclinedPlayerNameOpcode(WorldPacket& recv_data); void HandleTotemDestroy(WorldPacket& recv_data); diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index a62675c..16fa0e9 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -55,27 +55,41 @@ class MANGOS_DLL_SPEC Database QueryResult* PQuery(const char *format,...) ATTR_PRINTF(2,3); /// Async queries and query holders, implemented in DatabaseImpl.h + + // Query / member template bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql); template bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql); template bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql); + template + bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql); + // Query / static template bool AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql); template bool AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql); + template + bool AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql); + // PQuery / member template bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) ATTR_PRINTF(4,5); template bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6); template bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6); + template + bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(5,6); + // PQuery / static template bool AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6); template bool AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6); + template + bool AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(5,6); template + // QueryHolder bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder); template bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1); diff --git a/src/shared/Database/DatabaseImpl.h b/src/shared/Database/DatabaseImpl.h index d3eae74..0a150b7 100644 --- a/src/shared/Database/DatabaseImpl.h +++ b/src/shared/Database/DatabaseImpl.h @@ -21,84 +21,100 @@ /// Function body definitions for the template function members of the Database class +#define ASYNC_QUERY_BODY(new_sqlquery) \ + if (!sql) return false; \ + ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); \ + QueryQueues::iterator itr = m_queryQueues.find(queryThread); \ + if (itr == m_queryQueues.end()) return false; + +#define ASYNC_PQUERY_BODY \ + if(!format) return false; \ + \ + va_list ap; \ + char szQuery [MAX_QUERY_LEN]; \ + 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 \ + if (!holder) return false; \ + ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); \ + QueryQueues::iterator itr = m_queryQueues.find(queryThread); \ + if (itr == m_queryQueues.end()) return false; + +// -- Query / member -- + template bool Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql) { - if (!sql) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method), itr->second)); - return true; + ASYNC_QUERY_BODY + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method), itr->second)); } template bool Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql) { - if (!sql) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1), itr->second)); - return true; + ASYNC_QUERY_BODY + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1), itr->second)); } template bool Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) { - if (!sql) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1, param2), itr->second)); - return true; + ASYNC_QUERY_BODY + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1, param2), itr->second)); +} + +template +bool +Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql) +{ + ASYNC_QUERY_BODY + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, param1, param2, param3), itr->second)); } +// -- Query / static -- + template bool Database::AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql) { - if (!sql) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1), itr->second)); - return true; + ASYNC_QUERY_BODY + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1), itr->second)); } template bool Database::AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql) { - if (!sql) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1, param2), itr->second)); - return true; + ASYNC_QUERY_BODY + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1, param2), itr->second)); } -template +template bool -Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) +Database::AsyncQuery(void (*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql) { - if(!format) return false; + ASYNC_QUERY_BODY + return m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback(method, (QueryResult*)NULL, param1, param2, param3), itr->second)); +} - va_list ap; - char szQuery [MAX_QUERY_LEN]; - 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; - } +// -- PQuery / member -- +template +bool +Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) +{ + ASYNC_PQUERY_BODY return AsyncQuery(object, method, szQuery); } @@ -106,20 +122,7 @@ template bool Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) { - if(!format) return false; - - va_list ap; - char szQuery [MAX_QUERY_LEN]; - 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; - } - + ASYNC_PQUERY_BODY return AsyncQuery(object, method, param1, szQuery); } @@ -127,41 +130,25 @@ template bool Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) { - if(!format) return false; - - va_list ap; - char szQuery [MAX_QUERY_LEN]; - 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; - } - + ASYNC_PQUERY_BODY return AsyncQuery(object, method, param1, param2, szQuery); } -template +template bool -Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) +Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) { - if(!format) return false; + ASYNC_PQUERY_BODY + return AsyncQuery(object, method, param1, param2, param3, szQuery); +} - va_list ap; - char szQuery [MAX_QUERY_LEN]; - 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; - } +// -- PQuery / static -- +template +bool +Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) +{ + ASYNC_PQUERY_BODY return AsyncQuery(method, param1, szQuery); } @@ -169,43 +156,32 @@ template bool Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) { - if(!format) return false; - - va_list ap; - char szQuery [MAX_QUERY_LEN]; - 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; - } - + ASYNC_PQUERY_BODY return AsyncQuery(method, param1, param2, szQuery); } +template +bool +Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) +{ + ASYNC_PQUERY_BODY + return AsyncQuery(method, param1, param2, param3, szQuery); +} + +// -- QueryHolder -- + template bool Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder) { - if (!holder) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - holder->Execute(new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, holder), m_threadBody, itr->second); - return true; + ASYNC_DELAYHOLDER_BODY + return holder->Execute(new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, holder), m_threadBody, itr->second); } template bool Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1) { - if (!holder) return false; - ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current(); - QueryQueues::iterator itr = m_queryQueues.find(queryThread); - if (itr == m_queryQueues.end()) return false; - holder->Execute(new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, holder, param1), m_threadBody, itr->second); - return true; + ASYNC_DELAYHOLDER_BODY + return holder->Execute(new MaNGOS::QueryCallback(object, method, (QueryResult*)NULL, holder, param1), m_threadBody, itr->second); } diff --git a/src/shared/Database/SqlDelayThread.h b/src/shared/Database/SqlDelayThread.h index d80098d..7d3187a 100644 --- a/src/shared/Database/SqlDelayThread.h +++ b/src/shared/Database/SqlDelayThread.h @@ -40,7 +40,7 @@ class SqlDelayThread : public ZThread::Runnable SqlDelayThread(Database* db); ///< Put sql statement to delay queue - inline void Delay(SqlOperation* sql) { m_sqlQueue.add(sql); } + inline bool Delay(SqlOperation* sql) { m_sqlQueue.add(sql); return true; } virtual void Stop(); ///< Stop event virtual void run(); ///< Main Thread loop diff --git a/src/shared/Database/SqlOperations.cpp b/src/shared/Database/SqlOperations.cpp index bc75c59..70a1ff0 100644 --- a/src/shared/Database/SqlOperations.cpp +++ b/src/shared/Database/SqlOperations.cpp @@ -79,15 +79,16 @@ void SqlResultQueue::Update() } } -void SqlQueryHolder::Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue) +bool SqlQueryHolder::Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue) { if(!callback || !thread || !queue) - return; + 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) diff --git a/src/shared/Database/SqlOperations.h b/src/shared/Database/SqlOperations.h index a5aa911..41ae69e 100644 --- a/src/shared/Database/SqlOperations.h +++ b/src/shared/Database/SqlOperations.h @@ -104,7 +104,7 @@ class SqlQueryHolder void SetSize(size_t size); QueryResult* GetResult(size_t index); void SetResult(size_t index, QueryResult *result); - void Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue); + bool Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue); }; class SqlQueryHolderEx : public SqlOperation diff --git a/win/VC90/shared.vcproj b/win/VC90/shared.vcproj index 3254e55..5f8c07a 100644 --- a/win/VC90/shared.vcproj +++ b/win/VC90/shared.vcproj @@ -1,7 +1,7 @@ + + + + @@ -393,6 +401,30 @@ > + + + + + + + + + + + + @@ -405,6 +437,14 @@ > + + + +