From 8a7b77c0883eeefa6977f12c4395ab54f2bcc9fb Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Sun, 30 Aug 2009 14:04:18 +0400 Subject: [PATCH] [8441] Implement check DBs versions (required_* fields) at mangosd/realmd loading. * git_id updated to generate revision_sql.h file with required_* fields strings. * mangosd/realmd changed to include header and check this strings at startup. * mangosd/realmd will terminated if related strings not match in DB content. In most cases this meaning that not all expected sql updates applied. Current required_* field stored in DB output in error to help find what last sql updates applied. IMPORTNAT NOTE for mangos devs: please update used git_id before adding next commits with sql updates! --- contrib/git_id/git_id.cpp | 55 ++++++++++++++++++++++++++++---- src/mangosd/Master.cpp | 10 ++++++ src/realmd/Main.cpp | 4 +++ src/shared/Database/Database.cpp | 40 +++++++++++++++++++++++ src/shared/Database/Database.h | 1 + src/shared/revision_nr.h | 2 +- src/shared/revision_sql.h | 6 ++++ 7 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 src/shared/revision_sql.h diff --git a/contrib/git_id/git_id.cpp b/contrib/git_id/git_id.cpp index df81ac522..14bdf9165 100644 --- a/contrib/git_id/git_id.cpp +++ b/contrib/git_id/git_id.cpp @@ -58,7 +58,8 @@ char remotes[NUM_REMOTES][MAX_REMOTE] = { }; char remote_branch[MAX_REMOTE] = "master"; -char rev_file[MAX_PATH] = "src/shared/revision_nr.h"; +char rev_nr_file[MAX_PATH] = "src/shared/revision_nr.h"; +char rev_sql_file[MAX_PATH] = "src/shared/revision_sql.h"; char sql_update_dir[MAX_PATH] = "sql/updates"; char new_index_file[MAX_PATH] = ".git/git_id_index"; @@ -80,6 +81,12 @@ char db_sql_file[NUM_DATABASES][MAX_PATH] = { "sql/realmd.sql" }; +char db_sql_rev_field[NUM_DATABASES][MAX_PATH] = { + "REVISION_DB_CHARACTERS", + "REVISION_DB_MANGOS", + "REVISION_DB_REALMD" +}; + bool allow_replace = false; bool local = false; bool do_fetch = false; @@ -257,7 +264,7 @@ bool find_rev() return rev > 0; } -std::string generateHeader(char const* rev_str) +std::string generateNrHeader(char const* rev_str) { std::ostringstream newData; newData << "#ifndef __REVISION_NR_H__" << std::endl; @@ -267,6 +274,17 @@ std::string generateHeader(char const* rev_str) return newData.str(); } +std::string generateSqlHeader() +{ + std::ostringstream newData; + newData << "#ifndef __REVISION_SQL_H__" << std::endl; + newData << "#define __REVISION_SQL_H__" << std::endl; + for(int i = 0; i < NUM_DATABASES; ++i) + newData << " #define " << db_sql_rev_field[i] << " \"required_" << last_sql_update[i] << "\"" << std::endl; + newData << "#endif // __REVISION_SQL_H__" << std::endl; + return newData.str(); +} + void system_switch_index(const char *cmd) { // do the command for the original index and then for the new index @@ -280,15 +298,39 @@ void system_switch_index(const char *cmd) if(putenv(old_index_cmd) != 0) return; } -bool write_rev() +bool write_rev_nr() { printf("+ writing revision_nr.h\n"); char rev_str[256]; sprintf(rev_str, "%d", rev); - std::string header = generateHeader(rev_str); + std::string header = generateNrHeader(rev_str); char prefixed_file[MAX_PATH]; - snprintf(prefixed_file, MAX_PATH, "%s%s", path_prefix, rev_file); + snprintf(prefixed_file, MAX_PATH, "%s%s", path_prefix, rev_nr_file); + + if(FILE* OutputFile = fopen(prefixed_file, "wb")) + { + fprintf(OutputFile,"%s", header.c_str()); + fclose(OutputFile); + + // add the file to both indices, to be committed later + snprintf(cmd, MAX_CMD, "git add %s", prefixed_file); + system_switch_index(cmd); + + return true; + } + + return false; +} + +bool write_rev_sql() +{ + if(new_sql_updates.empty()) return true; + printf("+ writing revision_sql.h\n"); + std::string header = generateSqlHeader(); + + char prefixed_file[MAX_PATH]; + snprintf(prefixed_file, MAX_PATH, "%s%s", path_prefix, rev_sql_file); if(FILE* OutputFile = fopen(prefixed_file, "wb")) { @@ -846,12 +888,13 @@ int main(int argc, char *argv[]) if(do_sql) DO( find_sql_updates() ); DO( prepare_new_index() ); - DO( write_rev() ); + DO( write_rev_nr() ); if(do_sql) { DO( convert_sql_updates() ); DO( generate_sql_makefile() ); DO( change_sql_database() ); + DO( write_rev_sql() ); } DO( amend_commit() ); DO( cleanup_new_index() ); diff --git a/src/mangosd/Master.cpp b/src/mangosd/Master.cpp index 996cade19..7cb6c1011 100644 --- a/src/mangosd/Master.cpp +++ b/src/mangosd/Master.cpp @@ -38,6 +38,7 @@ #include "RASocket.h" #include "ScriptCalls.h" #include "Util.h" +#include "revision_sql.h" #include "sockets/TcpSocket.h" #include "sockets/Utility.h" @@ -416,6 +417,9 @@ bool Master::_StartDB() return false; } + if(!WorldDatabase.CheckRequiredField("db_version",REVISION_DB_MANGOS)) + return false; + if(!sConfig.GetString("CharacterDatabaseInfo", &dbstring)) { sLog.outError("Character Database not specified in configuration file"); @@ -430,6 +434,9 @@ bool Master::_StartDB() return false; } + if(!CharacterDatabase.CheckRequiredField("character_db_version",REVISION_DB_CHARACTERS)) + return false; + ///- Get login database info from configuration file if(!sConfig.GetString("LoginDatabaseInfo", &dbstring)) { @@ -445,6 +452,9 @@ bool Master::_StartDB() return false; } + if(!loginDatabase.CheckRequiredField("realmd_db_version",REVISION_DB_REALMD)) + return false; + ///- Get the realm Id from the configuration file realmID = sConfig.GetIntDefault("RealmID", 0); if(!realmID) diff --git a/src/realmd/Main.cpp b/src/realmd/Main.cpp index 777ad05c8..9080cf06f 100644 --- a/src/realmd/Main.cpp +++ b/src/realmd/Main.cpp @@ -31,6 +31,7 @@ #include "SystemConfig.h" #include "revision.h" #include "revision_nr.h" +#include "revision_sql.h" #include "Util.h" #include #include @@ -325,6 +326,9 @@ bool StartDB(std::string &dbstring) return false; } + if(!loginDatabase.CheckRequiredField("realmd_db_version",REVISION_DB_REALMD)) + return false; + return true; } diff --git a/src/shared/Database/Database.cpp b/src/shared/Database/Database.cpp index 58dc18c47..6bca7c967 100644 --- a/src/shared/Database/Database.cpp +++ b/src/shared/Database/Database.cpp @@ -189,3 +189,43 @@ bool Database::DirectPExecute(const char * format,...) return DirectExecute(szQuery); } + +bool Database::CheckRequiredField( char const* table_name, char const* required_name ) +{ + // check required field + 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 + + // search current required_* field in DB + 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 result; + + if(!reqName.empty()) + { + sLog.outErrorDb("Table `%s` have field `%s` but expected `%s`! Not all sql updates applied?",table_name,reqName.c_str(),required_name); + return false; + } + } + + sLog.outErrorDb("Table `%s` not have required_* field but expected `%s`! Not all sql updates applied?",table_name,required_name); + return false; +} \ No newline at end of file diff --git a/src/shared/Database/Database.h b/src/shared/Database/Database.h index d7dfd23e2..5935692d2 100644 --- a/src/shared/Database/Database.h +++ b/src/shared/Database/Database.h @@ -129,6 +129,7 @@ class MANGOS_DLL_SPEC Database // sets the result queue of the current thread, be careful what thread you call this from void SetResultQueue(SqlResultQueue * queue); + bool CheckRequiredField(char const* table_name, char const* required_name); private: bool m_logSQL; std::string m_logsDir; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 7f65cc3a9..82bc4742b 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8440" + #define REVISION_NR "8441" #endif // __REVISION_NR_H__ diff --git a/src/shared/revision_sql.h b/src/shared/revision_sql.h new file mode 100644 index 000000000..6dfab5a59 --- /dev/null +++ b/src/shared/revision_sql.h @@ -0,0 +1,6 @@ +#ifndef __REVISION_SQL_H__ +#define __REVISION_SQL_H__ + #define REVISION_DB_CHARACTERS "required_8433_01_characters_character_account_data" + #define REVISION_DB_MANGOS "required_8416_01_mangos_spell_learn_spell" + #define REVISION_DB_REALMD "required_8332_01_realmd_realmcharacters" +#endif // __REVISION_SQL_H__