diff --git a/common/database/database_dump_service.cpp b/common/database/database_dump_service.cpp index 3aa528665..5aaf0a065 100644 --- a/common/database/database_dump_service.cpp +++ b/common/database/database_dump_service.cpp @@ -28,6 +28,7 @@ #include "../database_schema.h" #include "../file.h" #include "../process/process.h" +#include "../termcolor/rang.hpp" #include @@ -36,6 +37,7 @@ #else #include +#include #endif @@ -145,7 +147,7 @@ std::string DatabaseDumpService::GetQueryServTables() std::string DatabaseDumpService::GetSystemTablesList() { - auto system_tables = DatabaseSchema::GetServerTables(); + auto system_tables = DatabaseSchema::GetServerTables(); auto version_tables = DatabaseSchema::GetVersionTables(); system_tables.insert( @@ -199,7 +201,7 @@ std::string DatabaseDumpService::GetDumpFileNameWithPath() return GetSetDumpPath() + GetDumpFileName(); } -void DatabaseDumpService::Dump() +void DatabaseDumpService::DatabaseDump() { if (!IsMySQLInstalled()) { LogError("MySQL is not installed; Please check your PATH for a valid MySQL installation"); @@ -308,7 +310,7 @@ void DatabaseDumpService::Dump() if (IsDumpDropTableSyntaxOnly()) { std::vector tables = Strings::Split(tables_to_dump, ' '); - for (auto &table : tables) { + for (auto &table: tables) { std::cout << "DROP TABLE IF EXISTS `" << table << "`;" << std::endl; } @@ -323,6 +325,26 @@ void DatabaseDumpService::Dump() } } + LogSys.EnableConsoleLogging(); + + if (!pipe_file.empty()) { + std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath()); + auto r = File::GetContents(file); + if (!r.error.empty()) { + LogError("{}", r.error); + } + + for (auto &line: Strings::Split(r.contents, "\n")) { + if (Strings::Contains(line, "mysqldump:")) { + LogError("{}", line); + LogError("Database dump failed. Correct the error before continuing or trying again"); + LogError("This is to prevent data loss on behalf of the server operator"); + RemoveSqlBackup(); + std::exit(1); + } + } + } + if (!tables_to_dump.empty()) { LogInfo("Dumping Tables [{}]", Strings::Trim(tables_to_dump)); } @@ -343,6 +365,7 @@ void DatabaseDumpService::Dump() ) ); LogInfo("Compressed dump created at [{}.tar.gz]", GetDumpFileNameWithPath()); + RemoveSqlBackup(); } else if (Is7ZipAvailable()) { Process::execute( @@ -353,6 +376,7 @@ void DatabaseDumpService::Dump() ) ); LogInfo("Compressed dump created at [{}.zip]", GetDumpFileNameWithPath()); + RemoveSqlBackup(); } else { LogInfo("Compression requested, but no available compression binary was found"); @@ -535,3 +559,11 @@ void DatabaseDumpService::SetDumpMercTables(bool dump_merc_tables) { DatabaseDumpService::dump_merc_tables = dump_merc_tables; } + +void DatabaseDumpService::RemoveSqlBackup() +{ + std::string file = fmt::format("{}.sql", GetDumpFileNameWithPath()); + if (File::Exists(file)) { + std::filesystem::remove(file); + } +} diff --git a/common/database/database_dump_service.h b/common/database/database_dump_service.h index 06f39dda1..c146ece03 100644 --- a/common/database/database_dump_service.h +++ b/common/database/database_dump_service.h @@ -24,7 +24,7 @@ class DatabaseDumpService { public: - void Dump(); + void DatabaseDump(); bool IsDumpAllTables() const; void SetDumpAllTables(bool dump_all_tables); bool IsDumpWithNoData() const; @@ -92,6 +92,7 @@ private: std::string GetDumpFileNameWithPath(); std::string GetSetDumpPath(); std::string GetQueryServTables(); + void RemoveSqlBackup(); }; diff --git a/common/file.cpp b/common/file.cpp index 2e478aa5b..3dc943927 100644 --- a/common/file.cpp +++ b/common/file.cpp @@ -37,6 +37,7 @@ #include #include +#include namespace fs = std::filesystem; @@ -80,3 +81,26 @@ std::string File::GetCwd() { return fs::current_path().string(); } + +FileContentsResult File::GetContents(const std::string &file_name) +{ + std::string error; + std::ifstream f; + f.open(file_name); + std::string line; + std::string lines; + if (f.is_open()) { + while (f) { + std::getline(f, line); + lines += line + "\n"; + } + } + else { + error = fmt::format("Couldn't open file [{}]", file_name); + } + + return FileContentsResult{ + .contents = lines, + .error = error, + }; +} diff --git a/common/file.h b/common/file.h index c420b4c78..7991101c4 100644 --- a/common/file.h +++ b/common/file.h @@ -25,10 +25,16 @@ namespace fs = std::filesystem; +struct FileContentsResult { + std::string contents; + std::string error; +}; + class File { public: static bool Exists(const std::string &name); static void Makedir(const std::string& directory_name); + static FileContentsResult GetContents(const std::string &file_name); static std::string FindEqemuConfigPath(); static std::string GetCwd(); }; diff --git a/common/process/process.cpp b/common/process/process.cpp index 926c9700b..badb0fe11 100644 --- a/common/process/process.cpp +++ b/common/process/process.cpp @@ -4,7 +4,8 @@ std::string Process::execute(const std::string &cmd) { - std::shared_ptr pipe(popen(cmd.c_str(), "r"), pclose); + std::string command = fmt::format("{} 2>&1", cmd); + std::shared_ptr pipe(popen(command.c_str(), "r"), pclose); if (!pipe) { return "ERROR"; } char buffer[128]; std::string result; diff --git a/world/cli/database_dump.cpp b/world/cli/database_dump.cpp index b15edeb12..bce0b37b0 100644 --- a/world/cli/database_dump.cpp +++ b/world/cli/database_dump.cpp @@ -36,9 +36,7 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std: s->SetDumpPath(cmd("--dump-path").str()); } - /** - * Set Option - */ + // options s->SetDumpContentTables(cmd[{"--content-tables"}] || dump_all); s->SetDumpLoginServerTables(cmd[{"--login-tables"}] || dump_all); s->SetDumpPlayerTables(cmd[{"--player-tables"}] || dump_all); @@ -48,15 +46,11 @@ void WorldserverCLI::DatabaseDump(int argc, char **argv, argh::parser &cmd, std: s->SetDumpSystemTables(cmd[{"--system-tables"}] || dump_all); s->SetDumpQueryServerTables(cmd[{"--query-serv-tables"}] || dump_all); s->SetDumpAllTables(dump_all); - s->SetDumpWithNoData(cmd[{"--table-structure-only"}]); s->SetDumpTableLock(cmd[{"--table-lock"}]); s->SetDumpWithCompression(cmd[{"--compress"}]); s->SetDumpOutputToConsole(cmd[{"--dump-output-to-console"}]); s->SetDumpDropTableSyntaxOnly(cmd[{"--drop-table-syntax-only"}]); - /** - * Dump - */ - s->Dump(); + s->DatabaseDump(); }