[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!
This commit is contained in:
VladimirMangos 2009-08-30 14:04:18 +04:00
parent c9f475dfa0
commit 8a7b77c088
7 changed files with 111 additions and 7 deletions

View file

@ -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() );

View file

@ -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)

View file

@ -31,6 +31,7 @@
#include "SystemConfig.h"
#include "revision.h"
#include "revision_nr.h"
#include "revision_sql.h"
#include "Util.h"
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
@ -325,6 +326,9 @@ bool StartDB(std::string &dbstring)
return false;
}
if(!loginDatabase.CheckRequiredField("realmd_db_version",REVISION_DB_REALMD))
return false;
return true;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "8440"
#define REVISION_NR "8441"
#endif // __REVISION_NR_H__

View file

@ -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__