aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared/Updater
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/shared/Updater')
-rw-r--r--src/server/shared/Updater/DBUpdater.cpp452
-rw-r--r--src/server/shared/Updater/DBUpdater.h92
-rw-r--r--src/server/shared/Updater/UpdateFetcher.cpp410
-rw-r--r--src/server/shared/Updater/UpdateFetcher.h132
4 files changed, 0 insertions, 1086 deletions
diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/shared/Updater/DBUpdater.cpp
deleted file mode 100644
index c0dfd400efc..00000000000
--- a/src/server/shared/Updater/DBUpdater.cpp
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "DBUpdater.h"
-#include "Log.h"
-#include "GitRevision.h"
-#include "UpdateFetcher.h"
-#include "DatabaseLoader.h"
-#include "Config.h"
-
-#include <fstream>
-#include <iostream>
-#include <unordered_map>
-#include <boost/process.hpp>
-#include <boost/iostreams/device/file_descriptor.hpp>
-#include <boost/system/system_error.hpp>
-
-using namespace boost::process;
-using namespace boost::process::initializers;
-using namespace boost::iostreams;
-
-template<class T>
-std::string DBUpdater<T>::GetSourceDirectory()
-{
- std::string const entry = sConfigMgr->GetStringDefault("Updates.SourcePath", "");
- if (!entry.empty())
- return entry;
- else
- return GitRevision::GetSourceDirectory();
-}
-
-template<class T>
-std::string DBUpdater<T>::GetMySqlCli()
-{
- std::string const entry = sConfigMgr->GetStringDefault("Updates.MySqlCLIPath", "");
- if (!entry.empty())
- return entry;
- else
- return GitRevision::GetMySQLExecutable();
-}
-
-// Auth Database
-template<>
-std::string DBUpdater<LoginDatabaseConnection>::GetConfigEntry()
-{
- return "Updates.Auth";
-}
-
-template<>
-std::string DBUpdater<LoginDatabaseConnection>::GetTableName()
-{
- return "Auth";
-}
-
-template<>
-std::string DBUpdater<LoginDatabaseConnection>::GetBaseFile()
-{
- return DBUpdater<LoginDatabaseConnection>::GetSourceDirectory() + "/sql/base/auth_database.sql";
-}
-
-template<>
-bool DBUpdater<LoginDatabaseConnection>::IsEnabled(uint32 const updateMask)
-{
- // This way silences warnings under msvc
- return (updateMask & DatabaseLoader::DATABASE_LOGIN) ? true : false;
-}
-
-// World Database
-template<>
-std::string DBUpdater<WorldDatabaseConnection>::GetConfigEntry()
-{
- return "Updates.World";
-}
-
-template<>
-std::string DBUpdater<WorldDatabaseConnection>::GetTableName()
-{
- return "World";
-}
-
-template<>
-std::string DBUpdater<WorldDatabaseConnection>::GetBaseFile()
-{
- return GitRevision::GetFullDatabase();
-}
-
-template<>
-bool DBUpdater<WorldDatabaseConnection>::IsEnabled(uint32 const updateMask)
-{
- // This way silences warnings under msvc
- return (updateMask & DatabaseLoader::DATABASE_WORLD) ? true : false;
-}
-
-template<>
-BaseLocation DBUpdater<WorldDatabaseConnection>::GetBaseLocationType()
-{
- return LOCATION_DOWNLOAD;
-}
-
-// Character Database
-template<>
-std::string DBUpdater<CharacterDatabaseConnection>::GetConfigEntry()
-{
- return "Updates.Character";
-}
-
-template<>
-std::string DBUpdater<CharacterDatabaseConnection>::GetTableName()
-{
- return "Character";
-}
-
-template<>
-std::string DBUpdater<CharacterDatabaseConnection>::GetBaseFile()
-{
- return DBUpdater<CharacterDatabaseConnection>::GetSourceDirectory() + "/sql/base/characters_database.sql";
-}
-
-template<>
-bool DBUpdater<CharacterDatabaseConnection>::IsEnabled(uint32 const updateMask)
-{
- // This way silences warnings under msvc
- return (updateMask & DatabaseLoader::DATABASE_CHARACTER) ? true : false;
-}
-
-// Hotfix Database
-template<>
-std::string DBUpdater<HotfixDatabaseConnection>::GetConfigEntry()
-{
- return "Updates.Hotfix";
-}
-
-template<>
-std::string DBUpdater<HotfixDatabaseConnection>::GetTableName()
-{
- return "Hotfixes";
-}
-
-template<>
-std::string DBUpdater<HotfixDatabaseConnection>::GetBaseFile()
-{
- return GitRevision::GetHotfixesDatabase();
-}
-
-template<>
-bool DBUpdater<HotfixDatabaseConnection>::IsEnabled(uint32 const updateMask)
-{
- // This way silences warnings under msvc
- return (updateMask & DatabaseLoader::DATABASE_HOTFIX) ? true : false;
-}
-
-template<>
-BaseLocation DBUpdater<HotfixDatabaseConnection>::GetBaseLocationType()
-{
- return LOCATION_DOWNLOAD;
-}
-
-// All
-template<class T>
-BaseLocation DBUpdater<T>::GetBaseLocationType()
-{
- return LOCATION_REPOSITORY;
-}
-
-template<class T>
-bool DBUpdater<T>::CheckExecutable()
-{
- DBUpdater<T>::Path const exe(DBUpdater<T>::GetMySqlCli());
- if (!exists(exe))
- {
- // Check for mysql in path
- std::vector<std::string> args = {"--version"};
- uint32 ret;
- try
- {
- child c = execute(run_exe("mysql"), set_args(args), throw_on_error(), close_stdout());
- ret = wait_for_exit(c);
- }
- catch (boost::system::system_error&)
- {
- ret = EXIT_FAILURE;
- }
-
- if (ret == EXIT_FAILURE)
- {
- TC_LOG_FATAL("sql.updates", "Didn't find executeable mysql binary at \'%s\', correct the path in the *.conf (\"Updates.MySqlCLIPath\").",
- absolute(exe).generic_string().c_str());
-
- return false;
- }
- }
- return true;
-}
-
-template<class T>
-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! Has the user `CREATE` priviliges?", pool.GetConnectionInfo()->database.c_str());
- boost::filesystem::remove(temp);
- return false;
- }
-
- TC_LOG_INFO("sql.updates", "Done.");
- boost::filesystem::remove(temp);
- return true;
-}
-
-template<class T>
-bool DBUpdater<T>::Update(DatabaseWorkerPool<T>& pool)
-{
- if (!DBUpdater<T>::CheckExecutable())
- return false;
-
- TC_LOG_INFO("sql.updates", "Updating %s database...", DBUpdater<T>::GetTableName().c_str());
-
- Path const sourceDirectory(GetSourceDirectory());
-
- if (!is_directory(sourceDirectory))
- {
- TC_LOG_ERROR("sql.updates", "DBUpdater: Given source directory %s does not exist, skipped!", sourceDirectory.generic_string().c_str());
- return false;
- }
-
- UpdateFetcher updateFetcher(sourceDirectory, [&](std::string const& query) { DBUpdater<T>::Apply(pool, query); },
- [&](Path const& file) { DBUpdater<T>::ApplyFile(pool, file); },
- [&](std::string const& query) -> QueryResult { return DBUpdater<T>::Retrieve(pool, query); });
-
- UpdateResult result;
- try
- {
- result = updateFetcher.Update(
- sConfigMgr->GetBoolDefault("Updates.Redundancy", true),
- sConfigMgr->GetBoolDefault("Updates.AllowRehash", true),
- sConfigMgr->GetBoolDefault("Updates.ArchivedRedundancy", false),
- sConfigMgr->GetIntDefault("Updates.CleanDeadRefMaxCount", 3));
- }
- catch (UpdateException&)
- {
- return false;
- }
-
- std::string const info = Trinity::StringFormat("Containing " SZFMTD " new and " SZFMTD " archived updates.",
- result.recent, result.archived);
-
- if (!result.updated)
- TC_LOG_INFO("sql.updates", ">> %s database is up-to-date! %s", DBUpdater<T>::GetTableName().c_str(), info.c_str());
- else
- TC_LOG_INFO("sql.updates", ">> Applied " SZFMTD " %s. %s", result.updated, result.updated == 1 ? "query" : "queries", info.c_str());
-
- return true;
-}
-
-template<class T>
-bool DBUpdater<T>::Populate(DatabaseWorkerPool<T>& pool)
-{
- {
- QueryResult const result = Retrieve(pool, "SHOW TABLES");
- if (result && (result->GetRowCount() > 0))
- return true;
- }
-
- if (!DBUpdater<T>::CheckExecutable())
- return false;
-
- TC_LOG_INFO("sql.updates", "Database %s is empty, auto populating it...", DBUpdater<T>::GetTableName().c_str());
-
- std::string const p = DBUpdater<T>::GetBaseFile();
- if (p.empty())
- {
- TC_LOG_INFO("sql.updates", ">> No base file provided, skipped!");
- return true;
- }
-
- Path const base(p);
- if (!exists(base))
- {
- switch (DBUpdater<T>::GetBaseLocationType())
- {
- case LOCATION_REPOSITORY:
- {
- TC_LOG_ERROR("sql.updates", ">> Base file \"%s\" is missing, try to clone the source again.",
- base.generic_string().c_str());
-
- break;
- }
- case LOCATION_DOWNLOAD:
- {
- TC_LOG_ERROR("sql.updates", ">> File \"%s\" is missing, download it from \"http://www.trinitycore.org/f/files/category/1-database/\"" \
- " and place it in your server directory.", base.filename().generic_string().c_str());
- break;
- }
- }
- return false;
- }
-
- // Update database
- TC_LOG_INFO("sql.updates", ">> Applying \'%s\'...", base.generic_string().c_str());
- try
- {
- ApplyFile(pool, base);
- }
- catch (UpdateException&)
- {
- return false;
- }
-
- TC_LOG_INFO("sql.updates", ">> Done!");
- return true;
-}
-
-template<class T>
-QueryResult DBUpdater<T>::Retrieve(DatabaseWorkerPool<T>& pool, std::string const& query)
-{
- return pool.PQuery(query.c_str());
-}
-
-template<class T>
-void DBUpdater<T>::Apply(DatabaseWorkerPool<T>& pool, std::string const& query)
-{
- pool.DirectExecute(query.c_str());
-}
-
-template<class T>
-void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, Path const& path)
-{
- DBUpdater<T>::ApplyFile(pool, pool.GetConnectionInfo()->host, pool.GetConnectionInfo()->user, pool.GetConnectionInfo()->password,
- pool.GetConnectionInfo()->port_or_socket, pool.GetConnectionInfo()->database, path);
-}
-
-template<class T>
-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(7);
-
- // 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 here if host == "." because 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);
-
- // ToDo: use the existing query in memory as virtual file if possible
- file_descriptor_source source(path);
-
- uint32 ret;
- try
- {
- child c = execute(run_exe(DBUpdater<T>::GetMySqlCli().empty() ? "mysql" :
- boost::filesystem::absolute(DBUpdater<T>::GetMySqlCli()).generic_string()),
- set_args(args), bind_stdin(source), throw_on_error());
-
- ret = wait_for_exit(c);
- }
- catch (boost::system::system_error&)
- {
- ret = EXIT_FAILURE;
- }
-
- source.close();
-
- if (ret != EXIT_SUCCESS)
- {
- TC_LOG_FATAL("sql.updates", "Applying of file \'%s\' to database \'%s\' failed!" \
- " If you are an user pull the latest revision from the repository. If you are a developer fix your sql query.",
- path.generic_string().c_str(), pool.GetConnectionInfo()->database.c_str());
-
- throw UpdateException("update failed");
- }
-}
-
-template class DBUpdater<LoginDatabaseConnection>;
-template class DBUpdater<WorldDatabaseConnection>;
-template class DBUpdater<CharacterDatabaseConnection>;
-template class DBUpdater<HotfixDatabaseConnection>;
diff --git a/src/server/shared/Updater/DBUpdater.h b/src/server/shared/Updater/DBUpdater.h
deleted file mode 100644
index a2b12bed235..00000000000
--- a/src/server/shared/Updater/DBUpdater.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef DBUpdater_h__
-#define DBUpdater_h__
-
-#include "DatabaseEnv.h"
-
-#include <string>
-#include <boost/filesystem.hpp>
-
-class UpdateException : public std::exception
-{
-public:
- UpdateException(std::string const& msg) : _msg(msg) { }
- ~UpdateException() throw() { }
-
- char const* what() const throw() override { return _msg.c_str(); }
-
-private:
- std::string const _msg;
-};
-
-enum BaseLocation
-{
- LOCATION_REPOSITORY,
- LOCATION_DOWNLOAD
-};
-
-struct UpdateResult
-{
- UpdateResult()
- : updated(0), recent(0), archived(0) { }
-
- UpdateResult(size_t const updated_, size_t const recent_, size_t const archived_)
- : updated(updated_), recent(recent_), archived(archived_) { }
-
- size_t updated;
- size_t recent;
- size_t archived;
-};
-
-template <class T>
-class DBUpdater
-{
-public:
- using Path = boost::filesystem::path;
-
- static std::string GetSourceDirectory();
-
- static inline std::string GetConfigEntry();
-
- static inline std::string GetTableName();
-
- static std::string GetBaseFile();
-
- static bool IsEnabled(uint32 const updateMask);
-
- static BaseLocation GetBaseLocationType();
-
- static bool Create(DatabaseWorkerPool<T>& pool);
-
- static bool Update(DatabaseWorkerPool<T>& pool);
-
- static bool Populate(DatabaseWorkerPool<T>& pool);
-
-private:
- static std::string GetMySqlCli();
- static bool CheckExecutable();
-
- static QueryResult Retrieve(DatabaseWorkerPool<T>& pool, std::string const& query);
- static void Apply(DatabaseWorkerPool<T>& pool, std::string const& query);
- static void ApplyFile(DatabaseWorkerPool<T>& pool, Path const& path);
- static void 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);
-};
-
-#endif // DBUpdater_h__
diff --git a/src/server/shared/Updater/UpdateFetcher.cpp b/src/server/shared/Updater/UpdateFetcher.cpp
deleted file mode 100644
index ec023928b99..00000000000
--- a/src/server/shared/Updater/UpdateFetcher.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
- * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "UpdateFetcher.h"
-#include "Log.h"
-#include "Util.h"
-
-#include <fstream>
-#include <chrono>
-#include <vector>
-#include <sstream>
-#include <exception>
-#include <unordered_map>
-#include <openssl/sha.h>
-
-using namespace boost::filesystem;
-
-UpdateFetcher::UpdateFetcher(Path const& sourceDirectory,
- std::function<void(std::string const&)> const& apply,
- std::function<void(Path const& path)> const& applyFile,
- std::function<QueryResult(std::string const&)> const& retrieve) :
- _sourceDirectory(sourceDirectory), _apply(apply), _applyFile(applyFile),
- _retrieve(retrieve)
-{
-}
-
-UpdateFetcher::LocaleFileStorage UpdateFetcher::GetFileList() const
-{
- LocaleFileStorage files;
- DirectoryStorage directories = ReceiveIncludedDirectories();
- for (auto const& entry : directories)
- FillFileListRecursively(entry.path, files, entry.state, 1);
-
- return files;
-}
-
-void UpdateFetcher::FillFileListRecursively(Path const& path, LocaleFileStorage& storage, State const state, uint32 const depth) const
-{
- static uint32 const MAX_DEPTH = 10;
- static directory_iterator const end;
-
- for (directory_iterator itr(path); itr != end; ++itr)
- {
- if (is_directory(itr->path()))
- {
- if (depth < MAX_DEPTH)
- FillFileListRecursively(itr->path(), storage, state, depth + 1);
- }
- else if (itr->path().extension() == ".sql")
- {
- TC_LOG_TRACE("sql.updates", "Added locale file \"%s\".", itr->path().filename().generic_string().c_str());
-
- LocaleFileEntry const entry = { itr->path(), state };
-
- // Check for doubled filenames
- // Since elements are only compared through their filenames this is ok
- if (storage.find(entry) != storage.end())
- {
- TC_LOG_FATAL("sql.updates", "Duplicated filename occurred \"%s\", since updates are ordered " \
- "through its filename every name needs to be unique!", itr->path().generic_string().c_str());
-
- throw UpdateException("Updating failed, see the log for details.");
- }
-
- storage.insert(entry);
- }
- }
-}
-
-UpdateFetcher::DirectoryStorage UpdateFetcher::ReceiveIncludedDirectories() const
-{
- DirectoryStorage directories;
-
- QueryResult const result = _retrieve("SELECT `path`, `state` FROM `updates_include`");
- if (!result)
- return directories;
-
- do
- {
- Field* fields = result->Fetch();
-
- std::string path = fields[0].GetString();
- if (path.substr(0, 1) == "$")
- path = _sourceDirectory.generic_string() + path.substr(1);
-
- Path const p(path);
-
- if (!is_directory(p))
- {
- TC_LOG_WARN("sql.updates", "DBUpdater: Given update include directory \"%s\" isn't existing, skipped!", p.generic_string().c_str());
- continue;
- }
-
- DirectoryEntry const entry = { p, AppliedFileEntry::StateConvert(fields[1].GetString()) };
- directories.push_back(entry);
-
- TC_LOG_TRACE("sql.updates", "Added applied file \"%s\" from remote.", p.filename().generic_string().c_str());
-
- } while (result->NextRow());
-
- return directories;
-}
-
-UpdateFetcher::AppliedFileStorage UpdateFetcher::ReceiveAppliedFiles() const
-{
- AppliedFileStorage map;
-
- QueryResult result = _retrieve("SELECT `name`, `hash`, `state`, UNIX_TIMESTAMP(`timestamp`) FROM `updates` ORDER BY `name` ASC");
- if (!result)
- return map;
-
- do
- {
- Field* fields = result->Fetch();
-
- AppliedFileEntry const entry = { fields[0].GetString(), fields[1].GetString(),
- AppliedFileEntry::StateConvert(fields[2].GetString()), fields[3].GetUInt64() };
-
- map.insert(std::make_pair(entry.name, entry));
- }
- while (result->NextRow());
-
- return map;
-}
-
-UpdateFetcher::SQLUpdate UpdateFetcher::ReadSQLUpdate(boost::filesystem::path const& file) const
-{
- std::ifstream in(file.c_str());
- WPFatal(in.is_open(), "Could not read an update file.");
-
- auto const start_pos = in.tellg();
- in.ignore(std::numeric_limits<std::streamsize>::max());
- auto const char_count = in.gcount();
- in.seekg(start_pos);
-
- SQLUpdate const update(new std::string(char_count, char{}));
-
- in.read(&(*update)[0], update->size());
- in.close();
- return update;
-}
-
-UpdateResult UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash, bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const
-{
- LocaleFileStorage const available = GetFileList();
- AppliedFileStorage applied = ReceiveAppliedFiles();
-
- size_t countRecentUpdates = 0;
- size_t countArchivedUpdates = 0;
-
- // Count updates
- for (auto const& entry : applied)
- if (entry.second.state == RELEASED)
- ++countRecentUpdates;
- else
- ++countArchivedUpdates;
-
- // Fill hash to name cache
- HashToFileNameStorage hashToName;
- for (auto entry : applied)
- hashToName.insert(std::make_pair(entry.second.hash, entry.first));
-
- size_t importedUpdates = 0;
-
- for (auto const& availableQuery : available)
- {
- TC_LOG_DEBUG("sql.updates", "Checking update \"%s\"...", availableQuery.first.filename().generic_string().c_str());
-
- AppliedFileStorage::const_iterator iter = applied.find(availableQuery.first.filename().string());
- if (iter != applied.end())
- {
- // If redundancy is disabled skip it since the update is already applied.
- if (!redundancyChecks)
- {
- TC_LOG_DEBUG("sql.updates", ">> Update is already applied, skipping redundancy checks.");
- applied.erase(iter);
- continue;
- }
-
- // If the update is in an archived directory and is marked as archived in our database skip redundancy checks (archived updates never change).
- if (!archivedRedundancy && (iter->second.state == ARCHIVED) && (availableQuery.second == ARCHIVED))
- {
- TC_LOG_DEBUG("sql.updates", ">> Update is archived and marked as archived in database, skipping redundancy checks.");
- applied.erase(iter);
- continue;
- }
- }
-
- // Read update from file
- SQLUpdate const update = ReadSQLUpdate(availableQuery.first);
-
- // Calculate hash
- std::string const hash = CalculateHash(update);
-
- UpdateMode mode = MODE_APPLY;
-
- // Update is not in our applied list
- if (iter == applied.end())
- {
- // Catch renames (different filename but same hash)
- HashToFileNameStorage::const_iterator const hashIter = hashToName.find(hash);
- if (hashIter != hashToName.end())
- {
- // Check if the original file was removed if not we've got a problem.
- LocaleFileStorage::const_iterator localeIter;
- // Push localeIter forward
- for (localeIter = available.begin(); (localeIter != available.end()) &&
- (localeIter->first.filename().string() != hashIter->second); ++localeIter);
-
- // Conflict!
- if (localeIter != available.end())
- {
- TC_LOG_WARN("sql.updates", ">> Seems like update \"%s\" \'%s\' was renamed, but the old file is still there! " \
- "Trade it as a new file! (Probably its an unmodified copy of file \"%s\")",
- availableQuery.first.filename().string().c_str(), hash.substr(0, 7).c_str(),
- localeIter->first.filename().string().c_str());
- }
- // Its save to trade the file as renamed here
- else
- {
- TC_LOG_INFO("sql.updates", ">> Renaming update \"%s\" to \"%s\" \'%s\'.",
- hashIter->second.c_str(), availableQuery.first.filename().string().c_str(), hash.substr(0, 7).c_str());
-
- RenameEntry(hashIter->second, availableQuery.first.filename().string());
- applied.erase(hashIter->second);
- continue;
- }
- }
- // Apply the update if it was never seen before.
- else
- {
- TC_LOG_INFO("sql.updates", ">> Applying update \"%s\" \'%s\'...",
- availableQuery.first.filename().string().c_str(), hash.substr(0, 7).c_str());
- }
- }
- // Rehash the update entry if it is contained in our database but with an empty hash.
- else if (allowRehash && iter->second.hash.empty())
- {
- mode = MODE_REHASH;
-
- TC_LOG_INFO("sql.updates", ">> Re-hashing update \"%s\" \'%s\'...", availableQuery.first.filename().string().c_str(),
- hash.substr(0, 7).c_str());
- }
- else
- {
- // If the hash of the files differs from the one stored in our database reapply the update (because it was changed).
- if (iter->second.hash != hash)
- {
- TC_LOG_INFO("sql.updates", ">> Reapplying update \"%s\" \'%s\' -> \'%s\' (it changed)...", availableQuery.first.filename().string().c_str(),
- iter->second.hash.substr(0, 7).c_str(), hash.substr(0, 7).c_str());
- }
- else
- {
- // If the file wasn't changed and just moved update its state if necessary.
- if (iter->second.state != availableQuery.second)
- {
- TC_LOG_DEBUG("sql.updates", ">> Updating state of \"%s\" to \'%s\'...",
- availableQuery.first.filename().string().c_str(), AppliedFileEntry::StateConvert(availableQuery.second).c_str());
-
- UpdateState(availableQuery.first.filename().string(), availableQuery.second);
- }
-
- TC_LOG_DEBUG("sql.updates", ">> Update is already applied and is matching hash \'%s\'.", hash.substr(0, 7).c_str());
-
- applied.erase(iter);
- continue;
- }
- }
-
- uint32 speed = 0;
- AppliedFileEntry const file = { availableQuery.first.filename().string(), hash, availableQuery.second, 0 };
-
- switch (mode)
- {
- case MODE_APPLY:
- speed = Apply(availableQuery.first);
- /*no break*/
- case MODE_REHASH:
- UpdateEntry(file, speed);
- break;
- }
-
- if (iter != applied.end())
- applied.erase(iter);
-
- if (mode == MODE_APPLY)
- ++importedUpdates;
- }
-
- // Cleanup up orphaned entries if enabled
- if (!applied.empty())
- {
- bool const doCleanup = (cleanDeadReferencesMaxCount < 0) || (applied.size() <= static_cast<size_t>(cleanDeadReferencesMaxCount));
-
- for (auto const& entry : applied)
- {
- TC_LOG_WARN("sql.updates", ">> File \'%s\' was applied to the database but is missing in" \
- " your update directory now!", entry.first.c_str());
-
- if (doCleanup)
- TC_LOG_INFO("sql.updates", "Deleting orphaned entry \'%s\'...", entry.first.c_str());
- }
-
- if (doCleanup)
- CleanUp(applied);
- else
- {
- TC_LOG_ERROR("sql.updates", "Cleanup is disabled! There are " SZFMTD " dirty files that were applied to your database " \
- "but are now missing in your source directory!", applied.size());
- }
- }
-
- return UpdateResult(importedUpdates, countRecentUpdates, countArchivedUpdates);
-}
-
-std::string UpdateFetcher::CalculateHash(SQLUpdate const& query) const
-{
- // Calculate a Sha1 hash based on query content.
- unsigned char digest[SHA_DIGEST_LENGTH];
- SHA1((unsigned char*)query->c_str(), query->length(), (unsigned char*)&digest);
-
- return ByteArrayToHexStr(digest, SHA_DIGEST_LENGTH);
-}
-
-uint32 UpdateFetcher::Apply(Path const& path) const
-{
- using Time = std::chrono::high_resolution_clock;
-
- // Benchmark query speed
- auto const begin = Time::now();
-
- // Update database
- _applyFile(path);
-
- // Return time the query took to apply
- return std::chrono::duration_cast<std::chrono::milliseconds>(Time::now() - begin).count();
-}
-
-void UpdateFetcher::UpdateEntry(AppliedFileEntry const& entry, uint32 const speed) const
-{
- std::string const update = "REPLACE INTO `updates` (`name`, `hash`, `state`, `speed`) VALUES (\"" +
- entry.name + "\", \"" + entry.hash + "\", \'" + entry.GetStateAsString() + "\', " + std::to_string(speed) + ")";
-
- // Update database
- _apply(update);
-}
-
-void UpdateFetcher::RenameEntry(std::string const& from, std::string const& to) const
-{
- // Delete target if it exists
- {
- std::string const update = "DELETE FROM `updates` WHERE `name`=\"" + to + "\"";
-
- // Update database
- _apply(update);
- }
-
- // Rename
- {
- std::string const update = "UPDATE `updates` SET `name`=\"" + to + "\" WHERE `name`=\"" + from + "\"";
-
- // Update database
- _apply(update);
- }
-}
-
-void UpdateFetcher::CleanUp(AppliedFileStorage const& storage) const
-{
- if (storage.empty())
- return;
-
- std::stringstream update;
- size_t remaining = storage.size();
-
- update << "DELETE FROM `updates` WHERE `name` IN(";
-
- for (auto const& entry : storage)
- {
- update << "\"" << entry.first << "\"";
- if ((--remaining) > 0)
- update << ", ";
- }
-
- update << ")";
-
- // Update database
- _apply(update.str());
-}
-
-void UpdateFetcher::UpdateState(std::string const& name, State const state) const
-{
- std::string const update = "UPDATE `updates` SET `state`=\'" + AppliedFileEntry::StateConvert(state) + "\' WHERE `name`=\"" + name + "\"";
-
- // Update database
- _apply(update);
-}
diff --git a/src/server/shared/Updater/UpdateFetcher.h b/src/server/shared/Updater/UpdateFetcher.h
deleted file mode 100644
index 4ff8c93bc76..00000000000
--- a/src/server/shared/Updater/UpdateFetcher.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef UpdateFetcher_h__
-#define UpdateFetcher_h__
-
-#include <DBUpdater.h>
-
-#include <functional>
-#include <string>
-#include <memory>
-#include <vector>
-
-class UpdateFetcher
-{
- typedef boost::filesystem::path Path;
-
-public:
- UpdateFetcher(Path const& updateDirectory,
- std::function<void(std::string const&)> const& apply,
- std::function<void(Path const& path)> const& applyFile,
- std::function<QueryResult(std::string const&)> const& retrieve);
-
- UpdateResult Update(bool const redundancyChecks, bool const allowRehash,
- bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const;
-
-private:
- enum UpdateMode
- {
- MODE_APPLY,
- MODE_REHASH
- };
-
- enum State
- {
- RELEASED,
- ARCHIVED
- };
-
- struct AppliedFileEntry
- {
- AppliedFileEntry(std::string const& name_, std::string const& hash_, State state_, uint64 timestamp_)
- : name(name_), hash(hash_), state(state_), timestamp(timestamp_) { }
-
- std::string const name;
-
- std::string const hash;
-
- State const state;
-
- uint64 const timestamp;
-
- static inline State StateConvert(std::string const& state)
- {
- return (state == "RELEASED") ? RELEASED : ARCHIVED;
- }
-
- static inline std::string StateConvert(State const state)
- {
- return (state == RELEASED) ? "RELEASED" : "ARCHIVED";
- }
-
- std::string GetStateAsString() const
- {
- return StateConvert(state);
- }
- };
-
- struct DirectoryEntry
- {
- DirectoryEntry(Path const& path_, State state_) : path(path_), state(state_) { }
-
- Path const path;
-
- State const state;
- };
-
- typedef std::pair<Path, State> LocaleFileEntry;
-
- struct PathCompare
- {
- inline bool operator() (LocaleFileEntry const& left, LocaleFileEntry const& right) const
- {
- return left.first.filename().string() < right.first.filename().string();
- }
- };
-
- typedef std::set<LocaleFileEntry, PathCompare> LocaleFileStorage;
- typedef std::unordered_map<std::string, std::string> HashToFileNameStorage;
- typedef std::unordered_map<std::string, AppliedFileEntry> AppliedFileStorage;
- typedef std::vector<UpdateFetcher::DirectoryEntry> DirectoryStorage;
- typedef std::shared_ptr<std::string> SQLUpdate;
-
- LocaleFileStorage GetFileList() const;
- void FillFileListRecursively(Path const& path, LocaleFileStorage& storage, State const state, uint32 const depth) const;
-
- DirectoryStorage ReceiveIncludedDirectories() const;
- AppliedFileStorage ReceiveAppliedFiles() const;
-
- SQLUpdate ReadSQLUpdate(Path const& file) const;
- std::string CalculateHash(SQLUpdate const& query) const;
-
- uint32 Apply(Path const& path) const;
-
- void UpdateEntry(AppliedFileEntry const& entry, uint32 const speed = 0) const;
- void RenameEntry(std::string const& from, std::string const& to) const;
- void CleanUp(AppliedFileStorage const& storage) const;
-
- void UpdateState(std::string const& name, State const state) const;
-
- Path const _sourceDirectory;
-
- std::function<void(std::string const&)> const _apply;
- std::function<void(Path const& path)> const _applyFile;
- std::function<QueryResult(std::string const&)> const _retrieve;
-};
-
-#endif // UpdateFetcher_h__