Database revision refactor

This commit is contained in:
Foereaper 2015-08-20 00:22:34 +02:00
parent 025ca0692e
commit b37de3b83e
8 changed files with 131 additions and 104 deletions

View File

@ -116,7 +116,6 @@ bool ChatHandler::HandleServerInfoCommand(char* /*args*/)
{ SendSysMessage(LANG_USING_SCRIPT_LIB_NONE); } { SendSysMessage(LANG_USING_SCRIPT_LIB_NONE); }
PSendSysMessage(LANG_USING_WORLD_DB, sWorld.GetDBVersion()); PSendSysMessage(LANG_USING_WORLD_DB, sWorld.GetDBVersion());
PSendSysMessage(LANG_USING_EVENT_AI, sWorld.GetCreatureEventAIVersion());
PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum); PSendSysMessage(LANG_CONNECTED_USERS, activeClientsNum, maxActiveClientsNum, queuedClientsNum, maxQueuedClientsNum);
PSendSysMessage(LANG_UPTIME, str.c_str()); PSendSysMessage(LANG_UPTIME, str.c_str());

View File

@ -84,6 +84,9 @@
// WARDEN // WARDEN
#include "WardenCheckMgr.h" #include "WardenCheckMgr.h"
#include <iostream>
#include <sstream>
INSTANTIATE_SINGLETON_1(World); INSTANTIATE_SINGLETON_1(World);
extern void LoadGameObjectModelList(); extern void LoadGameObjectModelList();
@ -2066,22 +2069,25 @@ void World::UpdateMaxSessionCounters()
void World::LoadDBVersion() void World::LoadDBVersion()
{ {
QueryResult* result = WorldDatabase.Query("SELECT version, creature_ai_version FROM db_version LIMIT 1"); QueryResult* result = WorldDatabase.Query("SELECT version, structure, content FROM db_version ORDER BY version DESC, structure DESC, content DESC LIMIT 1");
if (result) if (result)
{ {
Field* fields = result->Fetch(); Field* fields = result->Fetch();
m_DBVersion = fields[0].GetCppString(); uint32 version = fields[0].GetUInt32();
m_CreatureEventAIVersion = fields[1].GetCppString(); uint32 structure = fields[1].GetUInt32();
uint32 content = fields[2].GetUInt32();
delete result; delete result;
std::stringstream ss;
ss << "Version: " << version << ", Structure: " << structure << ", Content: " << content;
m_DBVersion = ss.str();
} }
if (m_DBVersion.empty()) if (m_DBVersion.empty())
{ m_DBVersion = "Unknown world database."; } { m_DBVersion = "Unknown world database."; }
if (m_CreatureEventAIVersion.empty())
{ m_CreatureEventAIVersion = "Unknown creature EventAI."; }
} }
void World::setConfig(eConfigUInt32Values index, char const* fieldname, uint32 defvalue) void World::setConfig(eConfigUInt32Values index, char const* fieldname, uint32 defvalue)

View File

@ -601,7 +601,6 @@ class World
// used World DB version // used World DB version
void LoadDBVersion(); void LoadDBVersion();
char const* GetDBVersion() { return m_DBVersion.c_str(); } char const* GetDBVersion() { return m_DBVersion.c_str(); }
char const* GetCreatureEventAIVersion() { return m_CreatureEventAIVersion.c_str(); }
/** /**
@ -692,7 +691,6 @@ class World
// used versions // used versions
std::string m_DBVersion; std::string m_DBVersion;
std::string m_CreatureEventAIVersion;
// List of Maps that should be force-loaded on startup // List of Maps that should be force-loaded on startup
std::set<uint32>* m_configForceLoadMapIds; std::set<uint32>* m_configForceLoadMapIds;

View File

@ -465,7 +465,8 @@ bool Master::_StartDB()
return false; return false;
} }
if (!WorldDatabase.CheckRequiredField("db_version", REVISION_DB_MANGOS)) ///- Check the World database version
if(!WorldDatabase.CheckDatabaseVersion(DATABASE_WORLD))
{ {
///- Wait for already started DB delay threads to end ///- Wait for already started DB delay threads to end
WorldDatabase.HaltDelayThread(); WorldDatabase.HaltDelayThread();
@ -494,7 +495,8 @@ bool Master::_StartDB()
return false; return false;
} }
if (!CharacterDatabase.CheckRequiredField("character_db_version", REVISION_DB_CHARACTERS)) ///- Check the Character database version
if (!CharacterDatabase.CheckDatabaseVersion(DATABASE_CHARACTER))
{ {
///- Wait for already started DB delay threads to end ///- Wait for already started DB delay threads to end
WorldDatabase.HaltDelayThread(); WorldDatabase.HaltDelayThread();
@ -527,7 +529,8 @@ bool Master::_StartDB()
return false; return false;
} }
if (!LoginDatabase.CheckRequiredField("realmd_db_version", REVISION_DB_REALMD)) ///- Check the Realm database version
if (!LoginDatabase.CheckDatabaseVersion(DATABASE_REALMD))
{ {
///- Wait for already started DB delay threads to end ///- Wait for already started DB delay threads to end
WorldDatabase.HaltDelayThread(); WorldDatabase.HaltDelayThread();
@ -560,7 +563,6 @@ bool Master::_StartDB()
sWorld.LoadDBVersion(); sWorld.LoadDBVersion();
sLog.outString("Using World DB: %s", sWorld.GetDBVersion()); sLog.outString("Using World DB: %s", sWorld.GetDBVersion());
sLog.outString("Using creature EventAI: %s", sWorld.GetCreatureEventAIVersion());
sLog.outString(); sLog.outString();
return true; return true;
} }

@ -1 +1 @@
Subproject commit 9c9e7ae7919e1cd5ce1f454520b9adf3316e2137 Subproject commit da60a5b8481ce8e02cf24614287ebc0e4930d278

View File

@ -25,6 +25,7 @@
#include "DatabaseEnv.h" #include "DatabaseEnv.h"
#include "Config/Config.h" #include "Config/Config.h"
#include "Database/SqlOperations.h" #include "Database/SqlOperations.h"
#include "revision.h"
#include <ctime> #include <ctime>
#include <iostream> #include <iostream>
@ -452,92 +453,78 @@ bool Database::RollbackTransaction()
return true; return true;
} }
bool Database::CheckRequiredField(char const* table_name, char const* required_name) bool Database::CheckDatabaseVersion(DatabaseTypes database)
{ {
// check required field const DBVersion& dbversion = databaseVersions[database];
QueryResult* result = PQuery("SELECT %s FROM %s LIMIT 1", required_name, table_name);
if (result)
{
delete result;
return true;
}
// check fail, prepare readabale error message // Fetch the database version table information
QueryResult* result = Query("SELECT version, structure, content, description FROM db_version ORDER BY version DESC, structure DESC, content DESC LIMIT 1");
// search current required_* field in DB // db_version table does not exist or is empty
const char* db_name; if (!result)
if (!strcmp(table_name, "db_version")) {
{ db_name = "WORLD"; } sLog.outErrorDb("The table `db_version` in your [%s] database is missing or corrupt.", dbversion.dbname.c_str());
else if (!strcmp(table_name, "character_db_version"))
{ db_name = "CHARACTER"; }
else if (!strcmp(table_name, "realmd_db_version"))
{ db_name = "REALMD"; }
else
{ db_name = "UNKNOWN"; }
char const* req_sql_update_name = required_name + strlen("required_");
QueryNamedResult* result2 = PQueryNamed("SELECT * FROM %s LIMIT 1", table_name);
if (result2)
{
QueryFieldNames const& namesMap = result2->GetFieldNames();
std::string reqName;
for (QueryFieldNames::const_iterator itr = namesMap.begin(); itr != namesMap.end(); ++itr)
{
if (itr->substr(0, 9) == "required_")
{
reqName = *itr;
break;
}
}
delete result2;
std::string cur_sql_update_name = reqName.substr(strlen("required_"), reqName.npos);
if (!reqName.empty())
{
sLog.outErrorDb("The table `%s` in your [%s] database indicates that this database is out of date!", table_name, db_name);
sLog.outErrorDb();
sLog.outErrorDb(" [A] You have: --> `%s.sql`", cur_sql_update_name.c_str());
sLog.outErrorDb();
sLog.outErrorDb(" [B] You need: --> `%s.sql`", req_sql_update_name);
sLog.outErrorDb();
sLog.outErrorDb("You must apply all updates after [A] to [B] to use mangos with this database.");
sLog.outErrorDb("These updates are included in the sql/updates folder.");
sLog.outErrorDb("Please read the included [README] in sql/updates for instructions on updating.");
}
else
{
sLog.outErrorDb("The table `%s` in your [%s] database is missing its version info.", table_name, db_name);
sLog.outErrorDb("MaNGOS can not find the version info needed to check that the db is up to date.");
sLog.outErrorDb();
sLog.outErrorDb("This revision of MaNGOS requires a database updated to:");
sLog.outErrorDb("`%s.sql`", req_sql_update_name);
sLog.outErrorDb();
if (!strcmp(db_name, "WORLD"))
{ sLog.outErrorDb("Post this error to your database provider forum or find a solution there."); }
else
{ sLog.outErrorDb("Reinstall your [%s] database with the included sql file in the sql folder.", db_name); }
}
}
else
{
sLog.outErrorDb("The table `%s` in your [%s] database is missing or corrupt.", table_name, db_name);
sLog.outErrorDb("MaNGOS can not find the version info needed to check that the db is up to date.");
sLog.outErrorDb(); sLog.outErrorDb();
sLog.outErrorDb("This revision of mangos requires a database updated to:"); sLog.outErrorDb(" [A] You have database Version: MaNGOS can not verify your database version or its existence!");
sLog.outErrorDb("`%s.sql`", req_sql_update_name);
sLog.outErrorDb(); sLog.outErrorDb();
sLog.outErrorDb(" [B] You need database Version: %u", dbversion.expected_version);
if (!strcmp(db_name, "WORLD")) sLog.outErrorDb(" Structure: %u", dbversion.expected_structure);
{ sLog.outErrorDb("Post this error to your database provider forum or find a solution there."); } sLog.outErrorDb(" Content: %u", dbversion.expected_content);
else sLog.outErrorDb(" Description: %s", dbversion.description.c_str());
{ sLog.outErrorDb("Reinstall your [%s] database with the included sql file in the sql folder.", db_name); } sLog.outErrorDb();
sLog.outErrorDb("Please verify your database location or your database integrity.");
return false;
} }
return false; Field* fields = result->Fetch();
uint32 version = fields[0].GetUInt32();
uint32 structure = fields[1].GetUInt32();
uint32 content = fields[2].GetUInt32();
std::string description = fields[3].GetCppString();
delete result;
// Structure does not match the required version
if (structure != dbversion.expected_structure)
{
sLog.outErrorDb("The table `db_version` indicates that your [%s] database does not match the expected structure!", dbversion.dbname.c_str());
sLog.outErrorDb();
sLog.outErrorDb(" [A] You have database Version: %u", version);
sLog.outErrorDb(" Structure: %u", structure);
sLog.outErrorDb(" Content: %u", content);
sLog.outErrorDb(" Description: %s", description.c_str());
sLog.outErrorDb();
sLog.outErrorDb(" [B] You need database Version: %u", dbversion.expected_version);
sLog.outErrorDb(" Structure: %u", dbversion.expected_structure);
sLog.outErrorDb(" Content: %u", dbversion.expected_content);
sLog.outErrorDb(" Description: %s", dbversion.description.c_str());
sLog.outErrorDb();
sLog.outErrorDb("You must apply all updates after [A] to [B] to use MaNGOS with this database.");
sLog.outErrorDb("These updates are included in the database/%s/Updates folder.", dbversion.dbname.c_str());
return false;
}
// DB is not up to date, but structure is correct. Send warning but start core
if (version != dbversion.expected_version || content != dbversion.expected_content)
{
sLog.outErrorDb("The table `db_version` indicates that your [%s] database does not match the expected version!", dbversion.dbname.c_str());
sLog.outErrorDb();
sLog.outErrorDb(" [A] You have database Version: %u", version);
sLog.outErrorDb(" Structure: %u", structure);
sLog.outErrorDb(" Content: %u", content);
sLog.outErrorDb(" Description: %s", description.c_str());
sLog.outErrorDb();
sLog.outErrorDb(" [B] You need database Version: %u", dbversion.expected_version);
sLog.outErrorDb(" Structure: %u", dbversion.expected_structure);
sLog.outErrorDb(" Content: %u", dbversion.expected_content);
sLog.outErrorDb(" Description: %s", dbversion.description.c_str());
sLog.outErrorDb();
sLog.outErrorDb("You are missing content updates or you have content updates beyond the expected core version.");
sLog.outErrorDb("It is recommended to run ALL database updates up to the required core version.");
sLog.outErrorDb("These updates are included in the database/%s/Updates folder.", dbversion.dbname.c_str());
};
return true;
} }
bool Database::ExecuteStmt(const SqlStatementID& id, SqlStmtParameters* params) bool Database::ExecuteStmt(const SqlStatementID& id, SqlStmtParameters* params)

View File

@ -25,6 +25,7 @@
#ifndef DATABASE_H #ifndef DATABASE_H
#define DATABASE_H #define DATABASE_H
#include "revision.h"
#include "Threading/Threading.h" #include "Threading/Threading.h"
#include "Utilities/UnorderedMapSet.h" #include "Utilities/UnorderedMapSet.h"
#include "Database/SqlDelayThread.h" #include "Database/SqlDelayThread.h"
@ -43,6 +44,29 @@ class Database;
#define MAX_QUERY_LEN (32*1024) #define MAX_QUERY_LEN (32*1024)
enum DatabaseTypes
{
DATABASE_WORLD,
DATABASE_REALMD,
DATABASE_CHARACTER,
COUNT_DATABASES,
};
struct DBVersion
{
std::string dbname;
uint32 expected_version;
uint32 expected_structure;
uint32 expected_content;
std::string description;
};
const DBVersion databaseVersions[COUNT_DATABASES] = {
{ "World", WORLD_DB_VERSION_NR, WORLD_DB_STRUCTURE_NR, WORLD_DB_CONTENT_NR, WORLD_DB_UPDATE_DESCRIPTION }, // DATABASE_WORLD
{ "Realmd", REALMD_DB_VERSION_NR, REALMD_DB_STRUCTURE_NR, REALMD_DB_CONTENT_NR, WORLD_DB_UPDATE_DESCRIPTION }, // DATABASE_REALMD
{ "Character", CHAR_DB_VERSION_NR, CHAR_DB_STRUCTURE_NR, CHAR_DB_CONTENT_NR, WORLD_DB_UPDATE_DESCRIPTION }, // DATABASE_CHARACTER
};
/** /**
* @brief * @brief
* *
@ -613,13 +637,12 @@ class Database
void ProcessResultQueue(); void ProcessResultQueue();
/** /**
* @brief * @brief Function to check that the database version matches expected core version
* *
* @param table_name * @param DatabaseTypes
* @param required_name * @return bool
* @return bool */
*/ bool CheckDatabaseVersion(DatabaseTypes database);
bool CheckRequiredField(char const* table_name, char const* required_name);
/** /**
* @brief * @brief
* *

View File

@ -24,8 +24,20 @@
#ifndef MANGOS_H_REVISION #ifndef MANGOS_H_REVISION
#define MANGOS_H_REVISION #define MANGOS_H_REVISION
#define REVISION_NR "21000" #define REVISION_NR "21000"
#define REVISION_DB_CHARACTERS "required_21000_01_warden_action"
#define REVISION_DB_MANGOS "required_21000_18_Update_for_quest_502_and_5203" #define REALMD_DB_VERSION_NR 21
#define REVISION_DB_REALMD "required_20150722_01_realmcharacters_remove_constraint" #define REALMD_DB_STRUCTURE_NR 1
#define REALMD_DB_CONTENT_NR 0
#define REALMD_DB_UPDATE_DESCRIPTION "revision_refactor"
#define CHAR_DB_VERSION_NR 21
#define CHAR_DB_STRUCTURE_NR 1
#define CHAR_DB_CONTENT_NR 0
#define CHAR_DB_UPDATE_DESCRIPTION "revision_refactor"
#define WORLD_DB_VERSION_NR 21
#define WORLD_DB_STRUCTURE_NR 1
#define WORLD_DB_CONTENT_NR 0
#define WORLD_DB_UPDATE_DESCRIPTION "revision_refactor"
#endif // __REVISION_H__ #endif // __REVISION_H__