/* * Copyright (C) 2008-2015 TrinityCore * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #include "DatabaseLoader.h" #include "DBUpdater.h" #include "Config.h" #include DatabaseLoader::DatabaseLoader(std::string const& logger, uint32 const defaultUpdateMask) : _logger(logger), _autoSetup(sConfigMgr->GetBoolDefault("Updates.AutoSetup", true)), _updateFlags(sConfigMgr->GetIntDefault("Updates.EnableDatabases", defaultUpdateMask)) { } template DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool& pool, std::string const& name) { bool const updatesEnabledForThis = DBUpdater::IsEnabled(_updateFlags); _open.push(std::make_pair([this, name, updatesEnabledForThis, &pool]() -> bool { std::string const dbString = sConfigMgr->GetStringDefault(name + "DatabaseInfo", ""); if (dbString.empty()) { TC_LOG_ERROR(_logger.c_str(), "Database %s not specified in configuration file!", name.c_str()); return false; } uint8 const asyncThreads = uint8(sConfigMgr->GetIntDefault(name + "Database.WorkerThreads", 1)); if (asyncThreads < 1 || asyncThreads > 32) { TC_LOG_ERROR(_logger.c_str(), "%s database: invalid number of worker threads specified. " "Please pick a value between 1 and 32.", name.c_str()); return false; } uint8 const synchThreads = uint8(sConfigMgr->GetIntDefault(name + "Database.SynchThreads", 1)); pool.SetConnectionInfo(dbString, asyncThreads, synchThreads); if (uint32 error = pool.Open()) { // Database does not exist if ((error == ER_BAD_DB_ERROR) && updatesEnabledForThis && _autoSetup) { // Try to create the database and connect again if auto setup is enabled if (DBUpdater::Create(pool) && (!pool.Open())) error = 0; } // If the error wasn't handled quit if (error) { TC_LOG_ERROR("sql.driver", "\nDatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile " "for specific errors. Read wiki at http://www.trinitycore.info/display/tc/TrinityCore+Home", name.c_str()); return false; } } return true; }, [&pool]() { pool.Close(); })); // Populate and update only if updates are enabled for this pool if (updatesEnabledForThis) { _populate.push([this, name, &pool]() -> bool { if (!DBUpdater::Populate(pool)) { TC_LOG_ERROR(_logger.c_str(), "Could not populate the %s database, see log for details.", name.c_str()); return false; } return true; }); _update.push([this, name, &pool]() -> bool { if (!DBUpdater::Update(pool)) { TC_LOG_ERROR(_logger.c_str(), "Could not update the %s database, see log for details.", name.c_str()); return false; } return true; }); } _prepare.push([this, name, &pool]() -> bool { if (!pool.PrepareStatements()) { TC_LOG_ERROR(_logger.c_str(), "Could not prepare statements of the %s database, see log for details.", name.c_str()); return false; } return true; }); return *this; } bool DatabaseLoader::Load() { if (!_updateFlags) TC_LOG_INFO("sql.updates", "Automatic database updates are disabled for all databases!"); if (!OpenDatabases()) return false; if (!PopulateDatabases()) return false; if (!UpdateDatabases()) return false; if (!PrepareStatements()) return false; return true; } bool DatabaseLoader::OpenDatabases() { while (!_open.empty()) { std::pair> const load = _open.top(); if (load.first()) _close.push(load.second); else { // Close all loaded databases while (!_close.empty()) { _close.top()(); _close.pop(); } return false; } _open.pop(); } return true; } // Processes the elements of the given stack until a predicate returned false. bool DatabaseLoader::Process(std::stack& stack) { while (!stack.empty()) { if (!stack.top()()) return false; stack.pop(); } return true; } bool DatabaseLoader::PopulateDatabases() { return Process(_populate); } bool DatabaseLoader::UpdateDatabases() { return Process(_update); } bool DatabaseLoader::PrepareStatements() { return Process(_prepare); } template DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool& pool, std::string const& name); template DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool& pool, std::string const& name); template DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool& pool, std::string const& name); template DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool& pool, std::string const& name);