TrinityCore
DatabaseLoader.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "DatabaseLoader.h"
19#include "Config.h"
20#include "DatabaseEnv.h"
21#include "DBUpdater.h"
22#include "Log.h"
23
24#include <mysqld_error.h>
25
26DatabaseLoader::DatabaseLoader(std::string const& logger, uint32 const defaultUpdateMask)
27 : _logger(logger), _autoSetup(sConfigMgr->GetBoolDefault("Updates.AutoSetup", true)),
28 _updateFlags(sConfigMgr->GetIntDefault("Updates.EnableDatabases", defaultUpdateMask))
29{
30}
31
32template <class T>
34{
35 bool const updatesEnabledForThis = DBUpdater<T>::IsEnabled(_updateFlags);
36
37 _open.push([this, name, updatesEnabledForThis, &pool]() -> bool
38 {
39 std::string const dbString = sConfigMgr->GetStringDefault(name + "DatabaseInfo", "");
40 if (dbString.empty())
41 {
42 TC_LOG_ERROR(_logger, "Database {} not specified in configuration file!", name);
43 return false;
44 }
45
46 uint8 const asyncThreads = uint8(sConfigMgr->GetIntDefault(name + "Database.WorkerThreads", 1));
47 if (asyncThreads < 1 || asyncThreads > 32)
48 {
49 TC_LOG_ERROR(_logger, "{} database: invalid number of worker threads specified. "
50 "Please pick a value between 1 and 32.", name);
51 return false;
52 }
53
54 uint8 const synchThreads = uint8(sConfigMgr->GetIntDefault(name + "Database.SynchThreads", 1));
55
56 pool.SetConnectionInfo(dbString, asyncThreads, synchThreads);
57 if (uint32 error = pool.Open())
58 {
59 // Database does not exist
60 if ((error == ER_BAD_DB_ERROR) && updatesEnabledForThis && _autoSetup)
61 {
62 // Try to create the database and connect again if auto setup is enabled
63 if (DBUpdater<T>::Create(pool) && (!pool.Open()))
64 error = 0;
65 }
66
67 // If the error wasn't handled quit
68 if (error)
69 {
70 TC_LOG_ERROR("sql.driver", "\nDatabasePool {} NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile "
71 "for specific errors. Read wiki at https://www.trinitycore.info/display/tc/TrinityCore+Home", name);
72
73 return false;
74 }
75 }
76 // Add the close operation
77 _close.push([&pool]
78 {
79 pool.Close();
80 });
81 return true;
82 });
83
84 // Populate and update only if updates are enabled for this pool
85 if (updatesEnabledForThis)
86 {
87 _populate.push([this, name, &pool]() -> bool
88 {
89 if (!DBUpdater<T>::Populate(pool))
90 {
91 TC_LOG_ERROR(_logger, "Could not populate the {} database, see log for details.", name);
92 return false;
93 }
94 return true;
95 });
96
97 _update.push([this, name, &pool]() -> bool
98 {
99 if (!DBUpdater<T>::Update(pool))
100 {
101 TC_LOG_ERROR(_logger, "Could not update the {} database, see log for details.", name);
102 return false;
103 }
104 return true;
105 });
106 }
107
108 _prepare.push([this, name, &pool]() -> bool
109 {
110 if (!pool.PrepareStatements())
111 {
112 TC_LOG_ERROR(_logger, "Could not prepare statements of the {} database, see log for details.", name);
113 return false;
114 }
115 return true;
116 });
117
118 return *this;
119}
120
122{
123 if (!_updateFlags)
124 TC_LOG_INFO("sql.updates", "Automatic database updates are disabled for all databases!");
125
126 if (!OpenDatabases())
127 return false;
128
129 if (!PopulateDatabases())
130 return false;
131
132 if (!UpdateDatabases())
133 return false;
134
135 if (!PrepareStatements())
136 return false;
137
138 return true;
139}
140
142{
143 return Process(_open);
144}
145
147{
148 return Process(_populate);
149}
150
152{
153 return Process(_update);
154}
155
157{
158 return Process(_prepare);
159}
160
161bool DatabaseLoader::Process(std::queue<Predicate>& queue)
162{
163 while (!queue.empty())
164 {
165 if (!queue.front()())
166 {
167 // Close all open databases which have a registered close operation
168 while (!_close.empty())
169 {
170 _close.top()();
171 _close.pop();
172 }
173
174 return false;
175 }
176
177 queue.pop();
178 }
179 return true;
180}
181
182template TC_DATABASE_API
183DatabaseLoader& DatabaseLoader::AddDatabase<LoginDatabaseConnection>(DatabaseWorkerPool<LoginDatabaseConnection>&, std::string const&);
184template TC_DATABASE_API
185DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(DatabaseWorkerPool<CharacterDatabaseConnection>&, std::string const&);
186template TC_DATABASE_API
187DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(DatabaseWorkerPool<WorldDatabaseConnection>&, std::string const&);
188template TC_DATABASE_API
189DatabaseLoader& DatabaseLoader::AddDatabase<HotfixDatabaseConnection>(DatabaseWorkerPool<HotfixDatabaseConnection>&, std::string const&);
#define sConfigMgr
Definition: Config.h:61
uint8_t uint8
Definition: Define.h:144
#define TC_DATABASE_API
Definition: Define.h:111
uint32_t uint32
Definition: Define.h:142
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
if(posix_memalign(&__mallocedMemory, __align, __size)) return NULL
static bool IsEnabled(uint32 const updateMask)
std::queue< Predicate > _populate
std::string const _logger
bool const _autoSetup
DatabaseLoader(std::string const &logger, uint32 const defaultUpdateMask)
uint32 const _updateFlags
std::queue< Predicate > _prepare
std::queue< Predicate > _update
std::queue< Predicate > _open
std::stack< Closer > _close
bool Process(std::queue< Predicate > &queue)
DatabaseLoader & AddDatabase(DatabaseWorkerPool< T > &pool, std::string const &name)
bool PrepareStatements()
Prepares all prepared statements.
void SetConnectionInfo(std::string const &infoString, uint8 const asyncThreads, uint8 const synchThreads)