bool DBUpdaterUtil::CheckExecutable() { boost::filesystem::path exe(GetCorrectedMySQLExecutable()); if (!exists(exe)) { exe.clear(); if (auto path = Trinity::SearchExecutableInPath("mysql")) { exe = std::move(*path); if (!exe.empty() && exists(exe)) { // Correct the path to the cli corrected_path() = absolute(exe).generic_string(); return true; } } TC_LOG_FATAL("sql.updates", "Didn't find any executable MySQL binary at \'%s\' or in path, correct the path in the *.conf (\"MySQLExecutable\").", absolute(exe).generic_string().c_str()); return false; } return true; }
void MotionMaster::DelayedDelete(_Ty curr) { TC_LOG_FATAL("misc", "Unit (Entry %u) is trying to delete its updating MG (Type %u)!", _owner->GetEntry(), curr->GetMovementGeneratorType()); if (isStatic(curr)) return; _expList.push_back(curr); }
void MotionMaster::DelayedDelete(_Ty curr) { TC_LOG_FATAL(LOG_FILTER_GENERAL, "Unit (Entry %u) is trying to delete its updating MG (Type %u)!", _owner->GetEntry(), curr->GetMovementGeneratorType()); if (isStatic(curr)) return; if (!_expList) _expList = new ExpireList(); _expList->push_back(curr); }
void MotionMaster::DelayedDelete(MovementGenerator* curr) { TC_LOG_FATAL("misc", "Unit (Entry %u) is trying to delete its updating Movement Generator (Type %u)!", _owner->GetEntry(), curr->GetMovementGeneratorType()); if (IsStatic(curr)) return; if (!_expireList) _expireList = new ExpireList(); _expireList->push_back(curr); }
bool DBUpdater<T>::Create(DatabaseWorkerPool<T>& pool) { TC_LOG_INFO("sql.updates", "Database \"%s\" does not exist, do you want to create it? [yes (default) / no]: ", pool.GetConnectionInfo()->database.c_str()); std::string answer; std::getline(std::cin, answer); if (!answer.empty() && !(answer.substr(0, 1) == "y")) return false; TC_LOG_INFO("sql.updates", "Creating database \"%s\"...", pool.GetConnectionInfo()->database.c_str()); // Path of temp file static Path const temp("create_table.sql"); // Create temporary query to use external MySQL CLi std::ofstream file(temp.generic_string()); if (!file.is_open()) { TC_LOG_FATAL("sql.updates", "Failed to create temporary query file \"%s\"!", temp.generic_string().c_str()); return false; } file << "CREATE DATABASE `" << pool.GetConnectionInfo()->database << "` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci\n\n"; file.close(); try { DBUpdater<T>::ApplyFile(pool, pool.GetConnectionInfo()->host, pool.GetConnectionInfo()->user, pool.GetConnectionInfo()->password, pool.GetConnectionInfo()->port_or_socket, "", temp); } catch (UpdateException&) { TC_LOG_FATAL("sql.updates", "Failed to create database %s! Does the user (named in *.conf) have `CREATE`, `ALTER`, `DROP`, `INSERT` and `DELETE` privileges on the MySQL server?", pool.GetConnectionInfo()->database.c_str()); boost::filesystem::remove(temp); return false; } TC_LOG_INFO("sql.updates", "Done."); boost::filesystem::remove(temp); return true; }
Bag::~Bag() { for (uint8 i = 0; i < MAX_BAG_SIZE; ++i) if (Item* item = m_bagslot[i]) { if (item->IsInWorld()) { TC_LOG_FATAL("entities.player.items", "Item %u (slot %u, bag slot %u) in bag %u (slot %u, bag slot %u, m_bagslot %u) is to be deleted but is still in world.", item->GetEntry(), (uint32)item->GetSlot(), (uint32)item->GetBagSlot(), GetEntry(), (uint32)GetSlot(), (uint32)GetBagSlot(), (uint32)i); item->RemoveFromWorld(); } delete m_bagslot[i]; } }
void WorldListener::HandleOpen() { try { _worldSocket->bind(std::string("tcp://*:") + std::to_string(_worldListenPort)); } catch (zmqpp::zmq_internal_exception& ex) { TC_LOG_FATAL("server.ipc", "Could not bind to WorldserverListenPort %u. Exception: %s. Shutting down bnetserver.", _worldListenPort, ex.what()); abort(); } _poller->add(*_worldSocket); TC_LOG_INFO("server.ipc", "Listening on connections from worldservers on port %u...", _worldListenPort); }
bool MySQLConnection::_HandleMySQLErrno(uint32 errNo, uint8 attempts /*= 5*/) { switch (errNo) { case CR_SERVER_GONE_ERROR: case CR_SERVER_LOST: #ifdef CR_INVALID_CONN_HANDLE case CR_INVALID_CONN_HANDLE: #endif case CR_SERVER_LOST_EXTENDED: { if (m_Mysql) { TC_LOG_ERROR("sql.sql", "Lost the connection to the MySQL server!"); mysql_close(GetHandle()); m_Mysql = nullptr; } /*no break*/ } case CR_CONN_HOST_ERROR: { TC_LOG_INFO("sql.sql", "Attempting to reconnect to the MySQL server..."); m_reconnecting = true; uint32 const lErrno = Open(); if (!lErrno) { // Don't remove 'this' pointer unless you want to skip loading all prepared statements... if (!this->PrepareStatements()) { TC_LOG_FATAL("sql.sql", "Could not re-prepare statements!"); std::this_thread::sleep_for(std::chrono::seconds(10)); std::abort(); } TC_LOG_INFO("sql.sql", "Successfully reconnected to %s @%s:%s (%s).", m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous"); m_reconnecting = false; return true; } if ((--attempts) == 0) { // Shut down the server when the mysql server isn't // reachable for some time TC_LOG_FATAL("sql.sql", "Failed to reconnect to the MySQL server, " "terminating the server to prevent data corruption!"); // We could also initiate a shutdown through using std::raise(SIGTERM) std::this_thread::sleep_for(std::chrono::seconds(10)); std::abort(); } else { // It's possible this attempted reconnect throws 2006 at us. // To prevent crazy recursive calls, sleep here. std::this_thread::sleep_for(std::chrono::seconds(3)); // Sleep 3 seconds return _HandleMySQLErrno(lErrno, attempts); // Call self (recursive) } } case ER_LOCK_DEADLOCK: return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction // Query related errors - skip query case ER_WRONG_VALUE_COUNT: case ER_DUP_ENTRY: return false; // Outdated table or database structure - terminate core case ER_BAD_FIELD_ERROR: case ER_NO_SUCH_TABLE: TC_LOG_ERROR("sql.sql", "Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders."); std::this_thread::sleep_for(std::chrono::seconds(10)); std::abort(); return false; case ER_PARSE_ERROR: TC_LOG_ERROR("sql.sql", "Error while parsing SQL. Core fix required."); std::this_thread::sleep_for(std::chrono::seconds(10)); std::abort(); return false; default: TC_LOG_ERROR("sql.sql", "Unhandled MySQL errno %u. Unexpected behaviour possible.", errNo); return false; } }
// Writing - High-level functions bool PlayerDumpWriter::DumpTable(std::string& dump, uint32 guid, char const*tableFrom, char const*tableTo, DumpTableType type) { GUIDs const* guids = NULL; char const* fieldname = NULL; switch (type) { case DTT_ITEM: fieldname = "guid"; guids = &items; break; case DTT_ITEM_GIFT: fieldname = "item_guid"; guids = &items; break; case DTT_PET: fieldname = "owner"; break; case DTT_PET_TABLE: fieldname = "guid"; guids = &pets; break; case DTT_MAIL: fieldname = "receiver"; break; case DTT_MAIL_ITEM: fieldname = "mail_id"; guids = &mails; break; default: fieldname = "guid"; break; } // for guid set stop if set is empty if (guids && guids->empty()) return true; // nothing to do // setup for guids case start position GUIDs::const_iterator guids_itr; if (guids) guids_itr = guids->begin(); do { std::string wherestr; if (guids) // set case, get next guids string wherestr = GenerateWhereStr(fieldname, *guids, guids_itr); else // not set case, get single guid string wherestr = GenerateWhereStr(fieldname, guid); QueryResult result = CharacterDatabase.PQuery("SELECT * FROM %s WHERE %s", tableFrom, wherestr.c_str()); if (!result) return true; do { // collect guids switch (type) { case DTT_INVENTORY: StoreGUID(result, 3, items); // item guid collection (character_inventory.item) break; case DTT_PET: StoreGUID(result, 0, pets); // pet petnumber collection (character_pet.id) break; case DTT_MAIL: StoreGUID(result, 0, mails); // mail id collection (mail.id) break; case DTT_MAIL_ITEM: StoreGUID(result, 1, items); // item guid collection (mail_items.item_guid) break; case DTT_CHARACTER: { if (result->GetFieldCount() <= 64) // avoid crashes on next check { TC_LOG_FATAL("misc", "PlayerDumpWriter::DumpTable - Trying to access non-existing or wrong positioned field (`deleteInfos_Account`) in `characters` table."); return false; } if (result->Fetch()[64].GetUInt32()) // characters.deleteInfos_Account - if filled error return false; break; } default: break; } dump += CreateDumpString(tableTo, result); dump += "\n"; } while (result->NextRow()); } while (guids && guids_itr != guids->end()); // not set case iterate single time, set case iterate for all guids return true; }
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, Path const& path) { std::vector<std::string> args; args.reserve(8); // args[0] represents the program name args.push_back("mysql"); // CLI Client connection info args.push_back("-h" + host); args.push_back("-u" + user); if (!password.empty()) args.push_back("-p" + password); // Check if we want to connect through ip or socket (Unix only) #ifdef _WIN32 args.push_back("-P" + port_or_socket); #else if (!std::isdigit(port_or_socket[0])) { // We can't check if host == "." here, because it is named localhost if socket option is enabled args.push_back("-P0"); args.push_back("--protocol=SOCKET"); args.push_back("-S" + port_or_socket); } else // generic case args.push_back("-P" + port_or_socket); #endif // Set the default charset to utf8 args.push_back("--default-character-set=utf8"); // Set max allowed packet to 1 GB args.push_back("--max-allowed-packet=1GB"); // Database if (!database.empty()) args.push_back(database); // Invokes a mysql process which doesn't leak credentials to logs int const ret = Trinity::StartProcess(DBUpdaterUtil::GetCorrectedMySQLExecutable(), args, "sql.updates", path.generic_string(), true); if (ret != EXIT_SUCCESS) { TC_LOG_FATAL("sql.updates", "Applying of file \'%s\' to database \'%s\' failed!" \ " If you are a user, please pull the latest revision from the repository. " "Also make sure you have not applied any of the databases with your sql client. " "You cannot use auto-update system and import sql files from TrinityCore repository with your sql client. " "If you are a developer, please fix your sql query.", path.generic_string().c_str(), pool.GetConnectionInfo()->database.c_str()); throw UpdateException("update failed"); } }