AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
ModuleDatabasePool Class Referenceabstract

#include "ModuleDatabasePool.h"

Inheritance diagram for ModuleDatabasePool:
DatabaseUpdatePool

Public Member Functions

 ModuleDatabasePool ()
 
virtual ~ModuleDatabasePool ()
 
void SetConnectionInfo (std::string_view infoString, uint8 synchThreads)
 
uint32 Open ()
 
bool PrepareStatements ()
 
void Close ()
 
void Execute (std::string_view sql)
 
void DirectExecute (std::string_view sql) override
 
QueryResult Query (std::string_view sql) override
 
MySQLConnectionInfo const * GetConnectionInfo () const override
 
template<typename... Args>
void Execute (std::string_view sql, Args &&... args)
 Format variants, mirroring DatabaseWorkerPool.
 
template<typename... Args>
void DirectExecute (std::string_view sql, Args &&... args)
 
template<typename... Args>
QueryResult Query (std::string_view sql, Args &&... args)
 
void Execute (PreparedStatementBase *stmt)
 
PreparedQueryResult Query (PreparedStatementBase *stmt)
 
uint8 GetPreparedStatementParamCount (uint32 index) const
 
void DirectCommitTransaction (std::shared_ptr< TransactionBase > transaction)
 Synchronously commits the transaction on a free connection.
 
void KeepAlive ()
 Pings every idle connection to keep them alive.
 
- Public Member Functions inherited from DatabaseUpdatePool
virtual ~DatabaseUpdatePool ()=default
 

Protected Member Functions

virtual MySQLConnection * CreateConnection (MySQLConnectionInfo &connInfo)=0
 

Private Member Functions

MySQLConnection * GetFreeConnection ()
 

Private Attributes

MySQLConnectionInfo _connectionInfo
 
std::vector< std::unique_ptr< MySQLConnection > > _connections
 
std::vector< uint8 > _preparedStatementSize
 
uint8 _synchThreads
 

Detailed Description

Constructor & Destructor Documentation

◆ ModuleDatabasePool()

ModuleDatabasePool::ModuleDatabasePool ( )
32{
33}
uint8 _synchThreads
Definition ModuleDatabasePool.h:119
MySQLConnectionInfo _connectionInfo
Definition ModuleDatabasePool.h:116

◆ ~ModuleDatabasePool()

ModuleDatabasePool::~ModuleDatabasePool ( )
virtual
36{
37 Close();
38}
void Close()
Definition ModuleDatabasePool.cpp:108

References Close().

Member Function Documentation

◆ Close()

void ModuleDatabasePool::Close ( )
109{
110 _connections.clear();
111
113}
std::vector< uint8 > _preparedStatementSize
Definition ModuleDatabasePool.h:118
std::vector< std::unique_ptr< MySQLConnection > > _connections
Definition ModuleDatabasePool.h:117

References _connections, and _preparedStatementSize.

Referenced by Open(), PrepareStatements(), and ~ModuleDatabasePool().

◆ CreateConnection()

virtual MySQLConnection * ModuleDatabasePool::CreateConnection ( MySQLConnectionInfo &  connInfo)
protectedpure virtual

Referenced by Open().

◆ DirectCommitTransaction()

void ModuleDatabasePool::DirectCommitTransaction ( std::shared_ptr< TransactionBase >  transaction)

Synchronously commits the transaction on a free connection.

Handle MySQL Errno 1213 without extending deadlock to the core itself

200{
201 if (_connections.empty())
202 return;
203
205 int errorCode = conn->ExecuteTransaction(transaction);
206 if (!errorCode)
207 {
208 conn->Unlock();
209 return;
210 }
211
213 if (errorCode == ER_LOCK_DEADLOCK)
214 {
215 uint8 constexpr loopBreaker = 5;
216 for (uint8 i = 0; i < loopBreaker; ++i)
217 {
218 if (!conn->ExecuteTransaction(transaction))
219 break;
220 }
221 }
222
223 transaction->Cleanup();
224 conn->Unlock();
225}
std::uint8_t uint8
Definition Define.h:109
MySQLConnection * GetFreeConnection()
Definition ModuleDatabasePool.cpp:240
Definition MySQLConnection.h:55
int ExecuteTransaction(std::shared_ptr< TransactionBase > transaction)
Definition MySQLConnection.cpp:382
void Unlock()
Called by parent databasepool. Will let other threads access this connection.
Definition MySQLConnection.cpp:476

References _connections, MySQLConnection::ExecuteTransaction(), GetFreeConnection(), and MySQLConnection::Unlock().

◆ DirectExecute() [1/2]

void ModuleDatabasePool::DirectExecute ( std::string_view  sql)
overridevirtual

Implements DatabaseUpdatePool.

123{
124 if (sql.empty())
125 return;
126
127 if (_connections.empty())
128 return;
129
131 conn->Execute(sql);
132 conn->Unlock();
133}
bool Execute(std::string_view sql)
Definition MySQLConnection.cpp:175

References _connections, MySQLConnection::Execute(), GetFreeConnection(), and MySQLConnection::Unlock().

Referenced by Execute().

◆ DirectExecute() [2/2]

template<typename... Args>
void ModuleDatabasePool::DirectExecute ( std::string_view  sql,
Args &&...  args 
)
inline
77 {
78 if (sql.empty())
79 return;
80
81 DirectExecute(std::string_view(Acore::StringFormat(sql, std::forward<Args>(args)...)));
82 }
void DirectExecute(std::string_view sql) override
Definition ModuleDatabasePool.cpp:122
std::string StringFormat(FormatStringView fmt, Args &&... args)
Default AC string format function.
Definition StringFormat.h:44

References DatabaseUpdatePool::DirectExecute(), and Acore::StringFormat().

◆ Execute() [1/3]

void ModuleDatabasePool::Execute ( PreparedStatementBase *  stmt)

Prepared statements. The index space is defined by the module's connection class (DoPrepareStatements); parameter counts are recorded by PrepareStatements(), so building one before that call yields a zero-parameter statement. Both calls consume (delete) the statement, mirroring DatabaseWorkerPool.

156{
157 if (_connections.empty())
158 {
159 delete stmt;
160 return;
161 }
162
164 conn->Execute(stmt);
165 conn->Unlock();
166
167 delete stmt;
168}

References _connections, MySQLConnection::Execute(), GetFreeConnection(), and MySQLConnection::Unlock().

◆ Execute() [2/3]

void ModuleDatabasePool::Execute ( std::string_view  sql)
116{
117 // Synchronous for now - kept separate from DirectExecute so async execution
118 // can be added later without touching callers.
119 DirectExecute(sql);
120}

References DirectExecute().

◆ Execute() [3/3]

template<typename... Args>
void ModuleDatabasePool::Execute ( std::string_view  sql,
Args &&...  args 
)
inline

Format variants, mirroring DatabaseWorkerPool.

68 {
69 if (sql.empty())
70 return;
71
72 Execute(std::string_view(Acore::StringFormat(sql, std::forward<Args>(args)...)));
73 }
void Execute(std::string_view sql)
Definition ModuleDatabasePool.cpp:115

References Acore::StringFormat().

◆ GetConnectionInfo()

MySQLConnectionInfo const * ModuleDatabasePool::GetConnectionInfo ( ) const
overridevirtual

Implements DatabaseUpdatePool.

262{
263 return &_connectionInfo;
264}

References _connectionInfo.

◆ GetFreeConnection()

MySQLConnection * ModuleDatabasePool::GetFreeConnection ( )
private

Block forever until a connection is free

Must be matched with connection->Unlock() or you will get deadlocks

241{
242 uint8 i = 0;
243 auto const num_cons = _connections.size();
244 MySQLConnection* connection = nullptr;
245
247 for (;;)
248 {
249 connection = _connections[++i % num_cons].get();
251 if (connection->LockIfReady())
252 break;
253
254 if (i % num_cons == 0)
255 std::this_thread::yield();
256 }
257
258 return connection;
259}
bool LockIfReady()
Definition MySQLConnection.cpp:471

References _connections, and MySQLConnection::LockIfReady().

Referenced by DirectCommitTransaction(), DirectExecute(), Execute(), Query(), and Query().

◆ GetPreparedStatementParamCount()

uint8 ModuleDatabasePool::GetPreparedStatementParamCount ( uint32  index) const

Parameter count for a prepared statement index, for constructing typed PreparedStatement<T> objects module-side.

195{
196 return index < _preparedStatementSize.size() ? _preparedStatementSize[index] : 0;
197}

References _preparedStatementSize.

◆ KeepAlive()

void ModuleDatabasePool::KeepAlive ( )

Pings every idle connection to keep them alive.

Ping connections that are not busy; a locked connection is in use and alive.

228{
230 for (auto const& conn : _connections)
231 {
232 if (conn->LockIfReady())
233 {
234 conn->Ping();
235 conn->Unlock();
236 }
237 }
238}

References _connections.

◆ Open()

uint32 ModuleDatabasePool::Open ( )

Opens the configured number of synchronous connections. Returns 0 on success, or the MySQL error code of the first failed connection.

47{
48 if (!_synchThreads)
49 {
50 LOG_ERROR("sql.driver", "ModuleDatabasePool: database `{}` was configured with 0 synchronous connections, "
51 "at least one is required.", _connectionInfo.database);
52 return CR_UNKNOWN_ERROR;
53 }
54
55 Close();
56
57 for (uint8 i = 0; i < _synchThreads; ++i)
58 {
59 auto conn = std::unique_ptr<MySQLConnection>(CreateConnection(_connectionInfo));
60 uint32 result = conn->Open();
61 if (result != 0)
62 {
63 LOG_ERROR("sql.driver", "ModuleDatabasePool: could not open connection {}/{} to database `{}`, error {}",
64 i + 1, _synchThreads, _connectionInfo.database, result);
65 Close();
66 return result;
67 }
68
69 _connections.push_back(std::move(conn));
70 }
71
72 return 0;
73}
std::uint32_t uint32
Definition Define.h:107
#define LOG_ERROR(filterType__,...)
Definition Log.h:145
virtual MySQLConnection * CreateConnection(MySQLConnectionInfo &connInfo)=0
std::string database
Definition MySQLConnection.h:48

References _connectionInfo, _connections, _synchThreads, Close(), CreateConnection(), MySQLConnectionInfo::database, and LOG_ERROR.

◆ PrepareStatements()

bool ModuleDatabasePool::PrepareStatements ( )

Prepares the connection statements. Call after the schema exists (post create/populate/update), mirroring DatabaseLoader's ordering.

76{
77 for (auto const& conn : _connections)
78 {
79 conn->LockIfReady();
80 if (!conn->PrepareStatements())
81 {
82 conn->Unlock();
83 Close();
84 return false;
85 }
86
87 conn->Unlock();
88 }
89
90 if (!_connections.empty())
91 {
92 MySQLConnection const* conn = _connections.front().get();
93 _preparedStatementSize.assign(conn->m_stmts.size(), 0);
94 for (std::size_t i = 0; i < conn->m_stmts.size(); ++i)
95 {
96 if (MySQLPreparedStatement* stmt = conn->m_stmts[i].get())
97 {
98 uint32 const paramCount = stmt->GetParameterCount();
99 ASSERT(paramCount < std::numeric_limits<uint8>::max());
100 _preparedStatementSize[i] = static_cast<uint8>(paramCount);
101 }
102 }
103 }
104
105 return true;
106}
#define ASSERT
Definition Errors.h:68
PreparedStatementContainer m_stmts
Definition MySQLConnection.h:106
Definition MySQLPreparedStatement.h:34

References _connections, _preparedStatementSize, ASSERT, Close(), and MySQLConnection::m_stmts.

◆ Query() [1/3]

PreparedQueryResult ModuleDatabasePool::Query ( PreparedStatementBase *  stmt)

Delete proxy-class. Not needed anymore

171{
172 if (_connections.empty())
173 {
174 delete stmt;
175 return PreparedQueryResult(nullptr);
176 }
177
179 PreparedResultSet* result = conn->Query(stmt);
180 conn->Unlock();
181
183 delete stmt;
184
185 if (!result || !result->GetRowCount())
186 {
187 delete result;
188 return PreparedQueryResult(nullptr);
189 }
190
191 return PreparedQueryResult(result);
192}
std::shared_ptr< PreparedResultSet > PreparedQueryResult
Definition DatabaseEnvFwd.h:45
ResultSet * Query(std::string_view sql)
Definition MySQLConnection.cpp:310
Definition QueryResult.h:99
uint64 GetRowCount() const
Definition QueryResult.h:105

References _connections, GetFreeConnection(), PreparedResultSet::GetRowCount(), MySQLConnection::Query(), and MySQLConnection::Unlock().

◆ Query() [2/3]

QueryResult ModuleDatabasePool::Query ( std::string_view  sql)
overridevirtual

Implements DatabaseUpdatePool.

136{
137 if (_connections.empty())
138 return QueryResult(nullptr);
139
141 ResultSet* result = conn->Query(sql);
142 conn->Unlock();
143
144 // Mirror DatabaseWorkerPool<T>::Query semantics: nullptr for empty results,
145 // and the first row loaded before the result is handed out.
146 if (!result || !result->GetRowCount() || !result->NextRow())
147 {
148 delete result;
149 return QueryResult(nullptr);
150 }
151
152 return QueryResult(result);
153}
std::shared_ptr< ResultSet > QueryResult
Definition DatabaseEnvFwd.h:27
Definition QueryResult.h:49
uint64 GetRowCount() const
Definition QueryResult.h:55
bool NextRow()
Definition QueryResult.cpp:188

References _connections, GetFreeConnection(), ResultSet::GetRowCount(), ResultSet::NextRow(), MySQLConnection::Query(), and MySQLConnection::Unlock().

◆ Query() [3/3]

template<typename... Args>
QueryResult ModuleDatabasePool::Query ( std::string_view  sql,
Args &&...  args 
)
inline
86 {
87 if (sql.empty())
88 return QueryResult(nullptr);
89
90 return Query(std::string_view(Acore::StringFormat(sql, std::forward<Args>(args)...)));
91 }
QueryResult Query(std::string_view sql) override
Definition ModuleDatabasePool.cpp:135

References DatabaseUpdatePool::Query(), and Acore::StringFormat().

◆ SetConnectionInfo()

void ModuleDatabasePool::SetConnectionInfo ( std::string_view  infoString,
uint8  synchThreads 
)
41{
43 _synchThreads = synchThreads;
44}
Definition MySQLConnection.h:43

References _connectionInfo, and _synchThreads.

Member Data Documentation

◆ _connectionInfo

MySQLConnectionInfo ModuleDatabasePool::_connectionInfo
private

◆ _connections

std::vector<std::unique_ptr<MySQLConnection> > ModuleDatabasePool::_connections
private

◆ _preparedStatementSize

std::vector<uint8> ModuleDatabasePool::_preparedStatementSize
private

◆ _synchThreads

uint8 ModuleDatabasePool::_synchThreads
private

Referenced by Open(), and SetConnectionInfo().


The documentation for this class was generated from the following files: