AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
DBUpdater< T > Class Template Reference

#include "DBUpdater.h"

Public Types

using Path = std::filesystem::path
 

Public Member Functions

std::string GetConfigEntry ()
 
std::string GetTableName ()
 
std::string GetBaseFilesDirectory ()
 
bool IsEnabled (uint32 const updateMask)
 
std::string GetDBModuleName ()
 
std::string GetConfigEntry ()
 
std::string GetTableName ()
 
std::string GetBaseFilesDirectory ()
 
bool IsEnabled (uint32 const updateMask)
 
std::string GetDBModuleName ()
 
std::string GetConfigEntry ()
 
std::string GetTableName ()
 
std::string GetBaseFilesDirectory ()
 
bool IsEnabled (uint32 const updateMask)
 
std::string GetDBModuleName ()
 

Static Public Member Functions

static std::string GetConfigEntry ()
 
static std::string GetTableName ()
 
static std::string GetBaseFilesDirectory ()
 
static bool IsEnabled (uint32 const updateMask)
 
static BaseLocation GetBaseLocationType ()
 
static bool Create (DatabaseWorkerPool< T > &pool)
 
static bool Update (DatabaseWorkerPool< T > &pool, std::string_view modulesList={})
 
static bool Update (DatabaseWorkerPool< T > &pool, std::vector< std::string > const *setDirectories)
 
static bool Populate (DatabaseWorkerPool< T > &pool)
 
static std::string GetDBModuleName ()
 

Static Private Member Functions

static QueryResult Retrieve (DatabaseWorkerPool< T > &pool, std::string const &query)
 
static void Apply (DatabaseWorkerPool< T > &pool, std::string const &query)
 
static void ApplyFile (DatabaseWorkerPool< T > &pool, Path const &path)
 
static void ApplyFile (DatabaseWorkerPool< T > &pool, std::string const &host, std::string const &user, std::string const &password, std::string const &port_or_socket, std::string const &database, std::string const &ssl, Path const &path)
 

Detailed Description

template<class T>
class DBUpdater< T >

Member Typedef Documentation

◆ Path

template<class T >
using DBUpdater< T >::Path = std::filesystem::path

Member Function Documentation

◆ Apply()

template<class T >
void DBUpdater< T >::Apply ( DatabaseWorkerPool< T > &  pool,
std::string const &  query 
)
staticprivate
430{
431 pool.DirectExecute(query.c_str());
432}
void DirectExecute(std::string_view sql)
Definition: DatabaseWorkerPool.cpp:494

References DatabaseWorkerPool< T >::DirectExecute().

Referenced by DBUpdater< T >::Update().

◆ ApplyFile() [1/2]

template<class T >
void DBUpdater< T >::ApplyFile ( DatabaseWorkerPool< T > &  pool,
Path const &  path 
)
staticprivate
436{
439}
MySQLConnectionInfo const * GetConnectionInfo() const
Definition: DatabaseWorkerPool.h:57
std::string host
Definition: MySQLConnection.h:50
std::string port_or_socket
Definition: MySQLConnection.h:51
std::string user
Definition: MySQLConnection.h:47
std::string database
Definition: MySQLConnection.h:49
std::string ssl
Definition: MySQLConnection.h:52
std::string password
Definition: MySQLConnection.h:48
static void ApplyFile(DatabaseWorkerPool< T > &pool, Path const &path)
Definition: DBUpdater.cpp:435

References DBUpdater< T >::ApplyFile(), MySQLConnectionInfo::database, DatabaseWorkerPool< T >::GetConnectionInfo(), MySQLConnectionInfo::host, MySQLConnectionInfo::password, MySQLConnectionInfo::port_or_socket, MySQLConnectionInfo::ssl, and MySQLConnectionInfo::user.

Referenced by DBUpdater< T >::ApplyFile(), DBUpdater< T >::Create(), and DBUpdater< T >::Update().

◆ ApplyFile() [2/2]

template<class T >
void DBUpdater< T >::ApplyFile ( DatabaseWorkerPool< T > &  pool,
std::string const &  host,
std::string const &  user,
std::string const &  password,
std::string const &  port_or_socket,
std::string const &  database,
std::string const &  ssl,
Path const &  path 
)
staticprivate
444{
445 std::string configTempDir = sConfigMgr->GetOption<std::string>("TempDir", "");
446
447 auto tempDir = configTempDir.empty() ? std::filesystem::temp_directory_path().string() : configTempDir;
448
449 tempDir = Acore::String::AddSuffixIfNotExists(tempDir, std::filesystem::path::preferred_separator);
450
451 std::string confFileName = "mysql_ac.conf";
452
453 std::ofstream outfile (tempDir + confFileName);
454
455 outfile << "[client]\npassword = \"" << password << '"' << std::endl;
456
457 outfile.close();
458
459 std::vector<std::string> args;
460 args.reserve(9);
461
462 args.emplace_back("--defaults-extra-file="+tempDir + confFileName+"");
463
464 // CLI Client connection info
465 args.emplace_back("-h" + host);
466 args.emplace_back("-u" + user);
467
468 // Check if we want to connect through ip or socket (Unix only)
469#ifdef _WIN32
470
471 if (host == ".")
472 args.emplace_back("--protocol=PIPE");
473 else
474 args.emplace_back("-P" + port_or_socket);
475
476#else
477
478 if (!std::isdigit(port_or_socket[0]))
479 {
480 // We can't check if host == "." here, because it is named localhost if socket option is enabled
481 args.emplace_back("-P0");
482 args.emplace_back("--protocol=SOCKET");
483 args.emplace_back("-S" + port_or_socket);
484 }
485 else
486 // generic case
487 args.emplace_back("-P" + port_or_socket);
488
489#endif
490
491 // Set the default charset to utf8
492 args.emplace_back("--default-character-set=utf8");
493
494 // Set max allowed packet to 1 GB
495 args.emplace_back("--max-allowed-packet=1GB");
496
497#if !defined(MARIADB_VERSION_ID) && MYSQL_VERSION_ID >= 80000
498
499 if (ssl == "ssl")
500 args.emplace_back("--ssl-mode=REQUIRED");
501
502#else
503
504 if (ssl == "ssl")
505 args.emplace_back("--ssl");
506
507#endif
508
509 // Execute sql file
510 args.emplace_back("-e");
511 args.emplace_back(Acore::StringFormat("BEGIN; SOURCE %s; COMMIT;", path.generic_string().c_str()));
512
513 // Database
514 if (!database.empty())
515 args.emplace_back(database);
516
517 // Invokes a mysql process which doesn't leak credentials to logs
519 "sql.updates", "", true);
520
521 if (ret != EXIT_SUCCESS)
522 {
523 LOG_FATAL("sql.updates", "Applying of file \'{}\' to database \'{}\' failed!" \
524 " If you are a user, please pull the latest revision from the repository. "
525 "Also make sure you have not applied any of the databases with your sql client. "
526 "You cannot use auto-update system and import sql files from AzerothCore repository with your sql client. "
527 "If you are a developer, please fix your sql query.",
528 path.generic_string(), pool.GetConnectionInfo()->database);
529
530 throw UpdateException("update failed");
531 }
532}
#define sConfigMgr
Definition: Config.h:95
#define LOG_FATAL(filterType__,...)
Definition: Log.h:153
std::string StringFormat(Format &&fmt, Args &&... args)
Default AC string format function.
Definition: StringFormat.h:30
int StartProcess(std::string const &executable, std::vector< std::string > const &args, std::string const &logger, std::string input_file, bool secure)
Definition: StartProcess.cpp:160
AC_COMMON_API std::string AddSuffixIfNotExists(std::string str, const char suffix)
Util function to add a suffix char. Can be used to add a slash at the end of a path.
Definition: StringFormat.cpp:73
Definition: DBUpdater.h:38
static std::string GetCorrectedMySQLExecutable()
Definition: DBUpdater.cpp:32

References Acore::String::AddSuffixIfNotExists(), MySQLConnectionInfo::database, DatabaseWorkerPool< T >::GetConnectionInfo(), DBUpdaterUtil::GetCorrectedMySQLExecutable(), LOG_FATAL, sConfigMgr, Acore::StartProcess(), and Acore::StringFormat().

◆ Create()

template<class T >
bool DBUpdater< T >::Create ( DatabaseWorkerPool< T > &  pool)
static
172{
173 LOG_WARN("sql.updates", "Database \"{}\" does not exist", pool.GetConnectionInfo()->database);
174
175 const char* disableInteractive = std::getenv("AC_DISABLE_INTERACTIVE");
176
177 if (!sConfigMgr->isDryRun() && (disableInteractive == nullptr || std::strcmp(disableInteractive, "1") != 0))
178 {
179 std::cout << "Do you want to create it? [yes (default) / no]:" << std::endl;
180 std::string answer;
181 std::getline(std::cin, answer);
182 if (!answer.empty() && !(answer.substr(0, 1) == "y"))
183 return false;
184 }
185
186 LOG_INFO("sql.updates", "Creating database \"{}\"...", pool.GetConnectionInfo()->database);
187
188 // Path of temp file
189 static Path const temp("create_table.sql");
190
191 // Create temporary query to use external MySQL CLi
192 std::ofstream file(temp.generic_string());
193 if (!file.is_open())
194 {
195 LOG_FATAL("sql.updates", "Failed to create temporary query file \"{}\"!", temp.generic_string());
196 return false;
197 }
198
199 file << "CREATE DATABASE `" << pool.GetConnectionInfo()->database << "` DEFAULT CHARACTER SET UTF8MB4 COLLATE utf8mb4_general_ci;\n\n";
200 file.close();
201
202 try
203 {
205 pool.GetConnectionInfo()->port_or_socket, "", pool.GetConnectionInfo()->ssl, temp);
206 }
207 catch (UpdateException&)
208 {
209 LOG_FATAL("sql.updates", "Failed to create database {}! Does the user (named in *.conf) have `CREATE`, `ALTER`, `DROP`, `INSERT` and `DELETE` privileges on the MySQL server?", pool.GetConnectionInfo()->database);
210 std::filesystem::remove(temp);
211 return false;
212 }
213
214 LOG_INFO("sql.updates", "Done.");
215 LOG_INFO("sql.updates", " ");
216 std::filesystem::remove(temp);
217 return true;
218}
#define LOG_INFO(filterType__,...)
Definition: Log.h:165
#define LOG_WARN(filterType__,...)
Definition: Log.h:161
std::filesystem::path Path
Definition: DBUpdater.h:70

References DBUpdater< T >::ApplyFile(), MySQLConnectionInfo::database, DatabaseWorkerPool< T >::GetConnectionInfo(), MySQLConnectionInfo::host, LOG_FATAL, LOG_INFO, LOG_WARN, MySQLConnectionInfo::password, MySQLConnectionInfo::port_or_socket, sConfigMgr, MySQLConnectionInfo::ssl, and MySQLConnectionInfo::user.

◆ GetBaseFilesDirectory() [1/4]

std::string DBUpdater< LoginDatabaseConnection >::GetBaseFilesDirectory ( )
82{
83 return BuiltInConfig::GetSourceDirectory() + "/data/sql/base/db_auth/";
84}
AC_COMMON_API std::string GetSourceDirectory()
Definition: BuiltInConfig.cpp:42

References BuiltInConfig::GetSourceDirectory().

◆ GetBaseFilesDirectory() [2/4]

std::string DBUpdater< WorldDatabaseConnection >::GetBaseFilesDirectory ( )
114{
115 return BuiltInConfig::GetSourceDirectory() + "/data/sql/base/db_world/";
116}

References BuiltInConfig::GetSourceDirectory().

◆ GetBaseFilesDirectory() [3/4]

std::string DBUpdater< CharacterDatabaseConnection >::GetBaseFilesDirectory ( )
146{
147 return BuiltInConfig::GetSourceDirectory() + "/data/sql/base/db_characters/";
148}

References BuiltInConfig::GetSourceDirectory().

◆ GetBaseFilesDirectory() [4/4]

template<class T >
static std::string DBUpdater< T >::GetBaseFilesDirectory ( )
static

◆ GetBaseLocationType()

template<class T >
BaseLocation DBUpdater< T >::GetBaseLocationType
static
166{
167 return LOCATION_REPOSITORY;
168}
@ LOCATION_REPOSITORY
Definition: DBUpdater.h:51

References LOCATION_REPOSITORY.

◆ GetConfigEntry() [1/4]

std::string DBUpdater< LoginDatabaseConnection >::GetConfigEntry ( )
70{
71 return "Updates.Auth";
72}

◆ GetConfigEntry() [2/4]

std::string DBUpdater< WorldDatabaseConnection >::GetConfigEntry ( )
102{
103 return "Updates.World";
104}

◆ GetConfigEntry() [3/4]

std::string DBUpdater< CharacterDatabaseConnection >::GetConfigEntry ( )
134{
135 return "Updates.Character";
136}

◆ GetConfigEntry() [4/4]

template<class T >
static std::string DBUpdater< T >::GetConfigEntry ( )
inlinestatic

◆ GetDBModuleName() [1/4]

std::string DBUpdater< LoginDatabaseConnection >::GetDBModuleName ( )
95{
96 return "db-auth";
97}

◆ GetDBModuleName() [2/4]

std::string DBUpdater< WorldDatabaseConnection >::GetDBModuleName ( )
127{
128 return "db-world";
129}

◆ GetDBModuleName() [3/4]

std::string DBUpdater< CharacterDatabaseConnection >::GetDBModuleName ( )
159{
160 return "db-characters";
161}

◆ GetDBModuleName() [4/4]

template<class T >
static std::string DBUpdater< T >::GetDBModuleName ( )
static

Referenced by DBUpdater< T >::Update().

◆ GetTableName() [1/4]

std::string DBUpdater< LoginDatabaseConnection >::GetTableName ( )
76{
77 return "Auth";
78}

◆ GetTableName() [2/4]

std::string DBUpdater< WorldDatabaseConnection >::GetTableName ( )
108{
109 return "World";
110}

◆ GetTableName() [3/4]

std::string DBUpdater< CharacterDatabaseConnection >::GetTableName ( )
140{
141 return "Character";
142}

◆ GetTableName() [4/4]

template<class T >
static std::string DBUpdater< T >::GetTableName ( )
inlinestatic

◆ IsEnabled() [1/4]

bool DBUpdater< LoginDatabaseConnection >::IsEnabled ( uint32 const  updateMask)
88{
89 // This way silences warnings under msvc
90 return (updateMask & DatabaseLoader::DATABASE_LOGIN) ? true : false;
91}
@ DATABASE_LOGIN
Definition: DatabaseLoader.h:48

References DatabaseLoader::DATABASE_LOGIN.

◆ IsEnabled() [2/4]

bool DBUpdater< WorldDatabaseConnection >::IsEnabled ( uint32 const  updateMask)
120{
121 // This way silences warnings under msvc
122 return (updateMask & DatabaseLoader::DATABASE_WORLD) ? true : false;
123}
@ DATABASE_WORLD
Definition: DatabaseLoader.h:50

References DatabaseLoader::DATABASE_WORLD.

◆ IsEnabled() [3/4]

bool DBUpdater< CharacterDatabaseConnection >::IsEnabled ( uint32 const  updateMask)
152{
153 // This way silences warnings under msvc
154 return (updateMask & DatabaseLoader::DATABASE_CHARACTER) ? true : false;
155}
@ DATABASE_CHARACTER
Definition: DatabaseLoader.h:49

References DatabaseLoader::DATABASE_CHARACTER.

◆ IsEnabled() [4/4]

template<class T >
static bool DBUpdater< T >::IsEnabled ( uint32 const  updateMask)
static

◆ Populate()

template<class T >
bool DBUpdater< T >::Populate ( DatabaseWorkerPool< T > &  pool)
static
358{
359 {
360 QueryResult const result = Retrieve(pool, "SHOW TABLES");
361 if (result && (result->GetRowCount() > 0))
362 return true;
363 }
364
366 return false;
367
368 LOG_INFO("sql.updates", "Database {} is empty, auto populating it...", DBUpdater<T>::GetTableName());
369
370 std::string const DirPathStr = DBUpdater<T>::GetBaseFilesDirectory();
371
372 Path const DirPath(DirPathStr);
373 if (!std::filesystem::is_directory(DirPath))
374 {
375 LOG_ERROR("sql.updates", ">> Directory \"{}\" not exist", DirPath.generic_string());
376 return false;
377 }
378
379 if (DirPath.empty())
380 {
381 LOG_ERROR("sql.updates", ">> Directory \"{}\" is empty", DirPath.generic_string());
382 return false;
383 }
384
385 std::filesystem::directory_iterator const DirItr;
386 uint32 FilesCount = 0;
387
388 for (std::filesystem::directory_iterator itr(DirPath); itr != DirItr; ++itr)
389 {
390 if (itr->path().extension() == ".sql")
391 FilesCount++;
392 }
393
394 if (!FilesCount)
395 {
396 LOG_ERROR("sql.updates", ">> In directory \"{}\" not exist '*.sql' files", DirPath.generic_string());
397 return false;
398 }
399
400 for (std::filesystem::directory_iterator itr(DirPath); itr != DirItr; ++itr)
401 {
402 if (itr->path().extension() != ".sql")
403 continue;
404
405 LOG_INFO("sql.updates", ">> Applying \'{}\'...", itr->path().filename().generic_string());
406
407 try
408 {
409 ApplyFile(pool, itr->path());
410 }
411 catch (UpdateException&)
412 {
413 return false;
414 }
415 }
416
417 LOG_INFO("sql.updates", ">> Done!");
418 LOG_INFO("sql.updates", " ");
419 return true;
420}
std::uint32_t uint32
Definition: Define.h:108
#define LOG_ERROR(filterType__,...)
Definition: Log.h:157
std::shared_ptr< ResultSet > QueryResult
Definition: DatabaseEnvFwd.h:28
static bool CheckExecutable()
Definition: DBUpdater.cpp:40
Definition: DBUpdater.h:68
static QueryResult Retrieve(DatabaseWorkerPool< T > &pool, std::string const &query)
Definition: DBUpdater.cpp:423
static std::string GetBaseFilesDirectory()

References DBUpdaterUtil::CheckExecutable(), DBUpdater< T >::GetBaseFilesDirectory(), LOG_ERROR, and LOG_INFO.

◆ Retrieve()

template<class T >
QueryResult DBUpdater< T >::Retrieve ( DatabaseWorkerPool< T > &  pool,
std::string const &  query 
)
staticprivate
424{
425 return pool.Query(query.c_str());
426}
QueryResult Query(std::string_view sql)
Definition: DatabaseWorkerPool.cpp:188

References DatabaseWorkerPool< T >::Query().

Referenced by DBUpdater< T >::Update().

◆ Update() [1/2]

template<class T >
bool DBUpdater< T >::Update ( DatabaseWorkerPool< T > &  pool,
std::string_view  modulesList = {} 
)
static
222{
224 return false;
225
226 LOG_INFO("sql.updates", "Updating {} database...", DBUpdater<T>::GetTableName());
227
228 Path const sourceDirectory(BuiltInConfig::GetSourceDirectory());
229
230 if (!is_directory(sourceDirectory))
231 {
232 LOG_ERROR("sql.updates", "DBUpdater: The given source directory {} does not exist, change the path to the directory where your sql directory exists (for example c:\\source\\azerothcore). Shutting down.",
233 sourceDirectory.generic_string());
234 return false;
235 }
236
237 auto CheckUpdateTable = [&](std::string const& tableName)
238 {
239 auto checkTable = DBUpdater<T>::Retrieve(pool, Acore::StringFormatFmt("SHOW TABLES LIKE '{}'", tableName));
240 if (!checkTable)
241 {
242 LOG_WARN("sql.updates", "> Table '{}' not exist! Try add based table", tableName);
243
244 Path const temp(GetBaseFilesDirectory() + tableName + ".sql");
245
246 try
247 {
248 DBUpdater<T>::ApplyFile(pool, temp);
249 }
250 catch (UpdateException&)
251 {
252 LOG_FATAL("sql.updates", "Failed apply file to database {}! Does the user (named in *.conf) have `INSERT` and `DELETE` privileges on the MySQL server?", pool.GetConnectionInfo()->database);
253 return false;
254 }
255
256 return true;
257 }
258
259 return true;
260 };
261
262 if (!CheckUpdateTable("updates") || !CheckUpdateTable("updates_include"))
263 return false;
264
265 UpdateFetcher updateFetcher(sourceDirectory, [&](std::string const & query) { DBUpdater<T>::Apply(pool, query); },
266 [&](Path const & file) { DBUpdater<T>::ApplyFile(pool, file); },
267 [&](std::string const & query) -> QueryResult { return DBUpdater<T>::Retrieve(pool, query); }, DBUpdater<T>::GetDBModuleName(), modulesList);
268
269 UpdateResult result;
270 try
271 {
272 result = updateFetcher.Update(
273 sConfigMgr->GetOption<bool>("Updates.Redundancy", true),
274 sConfigMgr->GetOption<bool>("Updates.AllowRehash", true),
275 sConfigMgr->GetOption<bool>("Updates.ArchivedRedundancy", false),
276 sConfigMgr->GetOption<int32>("Updates.CleanDeadRefMaxCount", 3));
277 }
278 catch (UpdateException&)
279 {
280 return false;
281 }
282
283 std::string const info = Acore::StringFormatFmt("Containing {} new and {} archived updates.", result.recent, result.archived);
284
285 if (!result.updated)
286 LOG_INFO("sql.updates", ">> {} database is up-to-date! {}", DBUpdater<T>::GetTableName(), info);
287 else
288 LOG_INFO("sql.updates", ">> Applied {} {}. {}", result.updated, result.updated == 1 ? "query" : "queries", info);
289
290 LOG_INFO("sql.updates", " ");
291
292 return true;
293}
std::int32_t int32
Definition: Define.h:104
std::string StringFormatFmt(FormatString< Args... > fmt, Args &&... args)
Definition: StringFormat.h:48
static void Apply(DatabaseWorkerPool< T > &pool, std::string const &query)
Definition: DBUpdater.cpp:429
static std::string GetDBModuleName()
Definition: UpdateFetcher.h:30
Definition: UpdateFetcher.h:43

References DBUpdater< T >::Apply(), DBUpdater< T >::ApplyFile(), DBUpdaterUtil::CheckExecutable(), MySQLConnectionInfo::database, DatabaseWorkerPool< T >::GetConnectionInfo(), DBUpdater< T >::GetDBModuleName(), BuiltInConfig::GetSourceDirectory(), LOG_ERROR, LOG_FATAL, LOG_INFO, LOG_WARN, DBUpdater< T >::Retrieve(), sConfigMgr, and Acore::StringFormatFmt().

◆ Update() [2/2]

template<class T >
bool DBUpdater< T >::Update ( DatabaseWorkerPool< T > &  pool,
std::vector< std::string > const *  setDirectories 
)
static
297{
299 {
300 return false;
301 }
302
303 Path const sourceDirectory(BuiltInConfig::GetSourceDirectory());
304 if (!is_directory(sourceDirectory))
305 {
306 return false;
307 }
308
309 auto CheckUpdateTable = [&](std::string const& tableName)
310 {
311 auto checkTable = DBUpdater<T>::Retrieve(pool, Acore::StringFormatFmt("SHOW TABLES LIKE '{}'", tableName));
312 if (!checkTable)
313 {
314 Path const temp(GetBaseFilesDirectory() + tableName + ".sql");
315 try
316 {
317 DBUpdater<T>::ApplyFile(pool, temp);
318 }
319 catch (UpdateException&)
320 {
321 return false;
322 }
323
324 return true;
325 }
326
327 return true;
328 };
329
330 if (!CheckUpdateTable("updates") || !CheckUpdateTable("updates_include"))
331 {
332 return false;
333 }
334
335 UpdateFetcher updateFetcher(sourceDirectory, [&](std::string const & query) { DBUpdater<T>::Apply(pool, query); },
336 [&](Path const & file) { DBUpdater<T>::ApplyFile(pool, file); },
337 [&](std::string const & query) -> QueryResult { return DBUpdater<T>::Retrieve(pool, query); }, DBUpdater<T>::GetDBModuleName(), setDirectories);
338
339 UpdateResult result;
340 try
341 {
342 result = updateFetcher.Update(
343 sConfigMgr->GetOption<bool>("Updates.Redundancy", true),
344 sConfigMgr->GetOption<bool>("Updates.AllowRehash", true),
345 sConfigMgr->GetOption<bool>("Updates.ArchivedRedundancy", false),
346 sConfigMgr->GetOption<int32>("Updates.CleanDeadRefMaxCount", 3));
347 }
348 catch (UpdateException&)
349 {
350 return false;
351 }
352
353 return true;
354}

References DBUpdater< T >::Apply(), DBUpdater< T >::ApplyFile(), DBUpdaterUtil::CheckExecutable(), DBUpdater< T >::GetDBModuleName(), BuiltInConfig::GetSourceDirectory(), DBUpdater< T >::Retrieve(), sConfigMgr, and Acore::StringFormatFmt().