aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/shared')
-rw-r--r--src/server/shared/Database/DatabaseLoader.cpp3
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp4
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.cpp21
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.h2
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.cpp10
-rw-r--r--src/server/shared/Debugging/WheatyExceptionReport.h2
-rw-r--r--src/server/shared/Networking/Socket.h2
-rw-r--r--src/server/shared/Updater/DBUpdater.cpp13
-rw-r--r--src/server/shared/Updater/DBUpdater.h13
-rw-r--r--src/server/shared/Updater/UpdateFetcher.cpp19
-rw-r--r--src/server/shared/Updater/UpdateFetcher.h2
-rw-r--r--src/server/shared/Utilities/TaskScheduler.cpp34
-rw-r--r--src/server/shared/Utilities/TaskScheduler.h48
13 files changed, 139 insertions, 34 deletions
diff --git a/src/server/shared/Database/DatabaseLoader.cpp b/src/server/shared/Database/DatabaseLoader.cpp
index 25c400fdfa8..1d704100d93 100644
--- a/src/server/shared/Database/DatabaseLoader.cpp
+++ b/src/server/shared/Database/DatabaseLoader.cpp
@@ -117,6 +117,9 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::st
bool DatabaseLoader::Load()
{
+ if (!_updateFlags)
+ TC_LOG_INFO("sql.updates", "Automatic database updates are disabled for all databases!");
+
if (!OpenDatabases())
return false;
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index 277ccd4569a..53fc0bba831 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -276,7 +276,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_PLAYER_CURRENCY, "DELETE FROM character_currency WHERE CharacterGuid = ?", CONNECTION_ASYNC);
// Account data
- PrepareStatement(CHAR_SEL_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE accountId = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_ACCOUNT_DATA, "SELECT type, time, data FROM account_data WHERE accountId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_REP_ACCOUNT_DATA, "REPLACE INTO account_data (accountId, type, time, data) VALUES (?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_ACCOUNT_DATA, "DELETE FROM account_data WHERE accountId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_PLAYER_ACCOUNT_DATA, "SELECT type, time, data FROM character_account_data WHERE guid = ?", CONNECTION_ASYNC);
@@ -284,7 +284,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PrepareStatement(CHAR_DEL_PLAYER_ACCOUNT_DATA, "DELETE FROM character_account_data WHERE guid = ?", CONNECTION_ASYNC);
// Tutorials
- PrepareStatement(CHAR_SEL_TUTORIALS, "SELECT tut0, tut1, tut2, tut3, tut4, tut5, tut6, tut7 FROM account_tutorial WHERE accountId = ?", CONNECTION_SYNCH);
+ PrepareStatement(CHAR_SEL_TUTORIALS, "SELECT tut0, tut1, tut2, tut3, tut4, tut5, tut6, tut7 FROM account_tutorial WHERE accountId = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_HAS_TUTORIALS, "SELECT 1 FROM account_tutorial WHERE accountId = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_INS_TUTORIALS, "INSERT INTO account_tutorial(tut0, tut1, tut2, tut3, tut4, tut5, tut6, tut7, accountId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_TUTORIALS, "UPDATE account_tutorial SET tut0 = ?, tut1 = ?, tut2 = ?, tut3 = ?, tut4 = ?, tut5 = ?, tut6 = ?, tut7 = ? WHERE accountId = ?", CONNECTION_ASYNC);
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp
index 0b2967f8922..51a0217ac17 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp
@@ -34,12 +34,17 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED_ALL, "SELECT account.id, username FROM account, account_banned WHERE account.id = account_banned.id AND active = 1 GROUP BY account.id", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_BANNED_BY_USERNAME, "SELECT account.id, username FROM account, account_banned WHERE account.id = account_banned.id AND active = 1 AND username LIKE CONCAT('%%', ?, '%%') GROUP BY account.id", CONNECTION_SYNCH);
PrepareStatement(LOGIN_DEL_ACCOUNT_BANNED, "DELETE FROM account_banned WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION, "SELECT username, sessionkey FROM account WHERE id = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_CONTINUED_SESSION, "SELECT username, sessionkey FROM account WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_VS, "UPDATE account SET v = ?, s = ? WHERE username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_LOGON_COUNTRY, "SELECT country FROM ip2nation WHERE ip < ? ORDER BY ip DESC LIMIT 0,1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.sessionkey, ba.last_ip, ba.locked, a.expansion, a.mutetime, ba.locale, a.recruiter, ba.os, ba.id, aa.gmLevel, "
+ "bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id "
+ "FROM account a LEFT JOIN battlenet_accounts ba ON a.battlenet_account = ba.id LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID IN (-1, ?) "
+ "LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account_banned ab ON a.id = ab.id LEFT JOIN account r ON a.id = r.recruiter "
+ "WHERE a.username = ? ORDER BY aa.RealmID DESC LIMIT 1", CONNECTION_ASYNC);
+
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_EMAIL, "SELECT id, username FROM account WHERE email = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_BY_IP, "SELECT id, username FROM account WHERE last_ip = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_BY_ID, "SELECT 1 FROM account WHERE id = ?", CONNECTION_SYNCH);
@@ -83,8 +88,6 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_ACCOUNT_INFO, "SELECT a.username, a.last_ip, aa.gmlevel, a.expansion FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_GMLEVEL_TEST, "SELECT 1 FROM account_access WHERE id = ? AND gmlevel > ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS, "SELECT a.id, aa.gmlevel, aa.RealmID FROM account a LEFT JOIN account_access aa ON (a.id = aa.id) WHERE a.username = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_ACCOUNT_RECRUITER, "SELECT 1 FROM account WHERE recruiter = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_BANS, "SELECT 1 FROM account_banned WHERE id = ? AND active = 1 UNION SELECT 1 FROM ip_banned WHERE ip = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_WHOIS, "SELECT username, email, last_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_LAST_ATTEMPT_IP, "SELECT last_attempt_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_LAST_IP, "SELECT last_ip FROM account WHERE id = ?", CONNECTION_SYNCH);
@@ -103,7 +106,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_INS_FALP_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES ((SELECT id FROM account WHERE username = ?), 0, 1, ?, ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_ACCOUNT_ACCESS_BY_ID, "SELECT gmlevel, RealmID FROM account_access WHERE id = ? and (RealmID = ? OR RealmID = -1) ORDER BY gmlevel desc", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS, "SELECT permissionId, granted FROM rbac_account_permissions WHERE accountId = ? AND (realmId = ? OR realmId = -1) ORDER BY permissionId, realmId", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_SEL_RBAC_ACCOUNT_PERMISSIONS, "SELECT permissionId, granted FROM rbac_account_permissions WHERE accountId = ? AND (realmId = ? OR realmId = -1) ORDER BY permissionId, realmId", CONNECTION_BOTH);
PrepareStatement(LOGIN_INS_RBAC_ACCOUNT_PERMISSION, "INSERT INTO rbac_account_permissions (accountId, permissionId, granted, realmId) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE granted = VALUES(granted)", CONNECTION_ASYNC);
PrepareStatement(LOGIN_DEL_RBAC_ACCOUNT_PERMISSION, "DELETE FROM rbac_account_permissions WHERE accountId = ? AND permissionId = ? AND (realmId = ? OR realmId = -1)", CONNECTION_ASYNC);
@@ -113,10 +116,14 @@ void LoginDatabaseConnection::DoPrepareStatements()
#define BnetAccountInfo "ba.id, UPPER(ba.email), ba.locked, ba.lock_country, ba.last_ip, ba.failed_logins, bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, bab.unbandate = bab.bandate"
#define BnetGameAccountInfo "a.id, a.username, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, ab.unbandate = ab.bandate, aa.gmlevel"
- PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_INFO, "SELECT " BnetAccountInfo ", ba.sha_pass_hash, ba.v, ba.s, " BnetGameAccountInfo " FROM battlenet_accounts ba LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account a ON ba.id = a.battlenet_account LEFT JOIN account_banned ab ON a.id = ab.id LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID = -1 WHERE ba.email = ?", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_SEL_BNET_ACCOUNT_INFO, "SELECT " BnetAccountInfo ", ba.sha_pass_hash, ba.v, ba.s, " BnetGameAccountInfo
+ " FROM battlenet_accounts ba LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account a ON ba.id = a.battlenet_account"
+ " LEFT JOIN account_banned ab ON a.id = ab.id LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID = -1 WHERE ba.email = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_VS_FIELDS, "UPDATE battlenet_accounts SET v = ?, s = ? WHERE email = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_SESSION_KEY, "UPDATE battlenet_accounts SET sessionKey = ?, online = ? WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_SEL_BNET_RECONNECT_INFO, "SELECT " BnetAccountInfo ", ba.sessionKey, " BnetGameAccountInfo " FROM battlenet_accounts ba LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account a ON ba.id = a.battlenet_account LEFT JOIN account_banned ab ON a.id = ab.id LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID = -1 WHERE ba.email = ? AND a.username = ?", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_SEL_BNET_RECONNECT_INFO, "SELECT " BnetAccountInfo ", ba.sessionKey, " BnetGameAccountInfo
+ " FROM battlenet_accounts ba LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account a ON ba.id = a.battlenet_account"
+ " LEFT JOIN account_banned ab ON a.id = ab.id LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID = -1 WHERE ba.email = ? AND a.username = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_FAILED_LOGINS, "UPDATE battlenet_accounts SET failed_logins = failed_logins + 1 WHERE email = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO, "UPDATE battlenet_accounts SET last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS, "SELECT rc.numchars, r.id, r.Region, r.Battlegroup, r.gamebuild FROM realmcharacters rc INNER JOIN realmlist r ON rc.realmid = r.id WHERE rc.acctid = ?", CONNECTION_ASYNC);
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/shared/Database/Implementation/LoginDatabase.h
index c0aa178f199..06d13f29da3 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.h
+++ b/src/server/shared/Database/Implementation/LoginDatabase.h
@@ -101,8 +101,6 @@ enum LoginDatabaseStatements
LOGIN_SEL_ACCOUNT_INFO,
LOGIN_SEL_ACCOUNT_ACCESS_GMLEVEL_TEST,
LOGIN_SEL_ACCOUNT_ACCESS,
- LOGIN_SEL_ACCOUNT_RECRUITER,
- LOGIN_SEL_BANS,
LOGIN_SEL_ACCOUNT_WHOIS,
LOGIN_SEL_REALMLIST_SECURITY_LEVEL,
LOGIN_DEL_ACCOUNT,
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp
index e50cf42e439..e9f888f280d 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.cpp
+++ b/src/server/shared/Debugging/WheatyExceptionReport.cpp
@@ -62,6 +62,8 @@ HANDLE WheatyExceptionReport::m_hProcess;
SymbolPairs WheatyExceptionReport::symbols;
std::stack<SymbolDetail> WheatyExceptionReport::symbolDetails;
bool WheatyExceptionReport::stackOverflowException;
+bool WheatyExceptionReport::alreadyCrashed;
+std::mutex WheatyExceptionReport::alreadyCrashedLock;
// Declare global instance of class
WheatyExceptionReport g_WheatyExceptionReport;
@@ -74,6 +76,7 @@ WheatyExceptionReport::WheatyExceptionReport() // Constructor
m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter);
m_hProcess = GetCurrentProcess();
stackOverflowException = false;
+ alreadyCrashed = false;
if (!IsDebuggerPresent())
{
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
@@ -99,6 +102,13 @@ WheatyExceptionReport::~WheatyExceptionReport()
LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
PEXCEPTION_POINTERS pExceptionInfo)
{
+ std::unique_lock<std::mutex> guard(alreadyCrashedLock);
+ // Handle only 1 exception in the whole process lifetime
+ if (alreadyCrashed)
+ return EXCEPTION_EXECUTE_HANDLER;
+
+ alreadyCrashed = true;
+
if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW)
stackOverflowException = true;
diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h
index 101b6187f2b..ef6334add16 100644
--- a/src/server/shared/Debugging/WheatyExceptionReport.h
+++ b/src/server/shared/Debugging/WheatyExceptionReport.h
@@ -194,6 +194,8 @@ class WheatyExceptionReport
static SymbolPairs symbols;
static std::stack<SymbolDetail> symbolDetails;
static bool stackOverflowException;
+ static bool alreadyCrashed;
+ static std::mutex alreadyCrashedLock;
static char* PushSymbolDetail(char* pszCurrBuffer);
static char* PopSymbolDetail(char* pszCurrBuffer);
diff --git a/src/server/shared/Networking/Socket.h b/src/server/shared/Networking/Socket.h
index d337e07ff52..23c4f25b742 100644
--- a/src/server/shared/Networking/Socket.h
+++ b/src/server/shared/Networking/Socket.h
@@ -169,6 +169,8 @@ protected:
MessageBuffer _writeBuffer;
#endif
+ boost::asio::io_service& io_service() { return _socket.get_io_service(); }
+
private:
void ReadHandlerInternal(boost::system::error_code error, size_t transferredBytes)
{
diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/shared/Updater/DBUpdater.cpp
index 10c8c163ec4..c74b8ef868e 100644
--- a/src/server/shared/Updater/DBUpdater.cpp
+++ b/src/server/shared/Updater/DBUpdater.cpp
@@ -271,10 +271,10 @@ bool DBUpdater<T>::Update(DatabaseWorkerPool<T>& pool)
[&](Path const& file) { DBUpdater<T>::ApplyFile(pool, file); },
[&](std::string const& query) -> QueryResult { return DBUpdater<T>::Retrieve(pool, query); });
- uint32 count;
+ UpdateResult result;
try
{
- count = updateFetcher.Update(
+ result = updateFetcher.Update(
sConfigMgr->GetBoolDefault("Updates.Redundancy", true),
sConfigMgr->GetBoolDefault("Updates.AllowRehash", true),
sConfigMgr->GetBoolDefault("Updates.ArchivedRedundancy", false),
@@ -285,10 +285,13 @@ bool DBUpdater<T>::Update(DatabaseWorkerPool<T>& pool)
return false;
}
- if (!count)
- TC_LOG_INFO("sql.updates", ">> %s database is up-to-date!", DBUpdater<T>::GetTableName().c_str());
+ 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 %d %s.", count, count == 1 ? "query" : "queries");
+ TC_LOG_INFO("sql.updates", ">> Applied " SZFMTD " %s. %s", result.updated, result.updated == 1 ? "query" : "queries", info.c_str());
return true;
}
diff --git a/src/server/shared/Updater/DBUpdater.h b/src/server/shared/Updater/DBUpdater.h
index 0caf8a438fb..a2b12bed235 100644
--- a/src/server/shared/Updater/DBUpdater.h
+++ b/src/server/shared/Updater/DBUpdater.h
@@ -41,6 +41,19 @@ enum BaseLocation
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
{
diff --git a/src/server/shared/Updater/UpdateFetcher.cpp b/src/server/shared/Updater/UpdateFetcher.cpp
index a4bdd193743..ec023928b99 100644
--- a/src/server/shared/Updater/UpdateFetcher.cpp
+++ b/src/server/shared/Updater/UpdateFetcher.cpp
@@ -154,17 +154,27 @@ UpdateFetcher::SQLUpdate UpdateFetcher::ReadSQLUpdate(boost::filesystem::path co
return update;
}
-uint32 UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash, bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const
+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));
- uint32 importedUpdates = 0;
+ size_t importedUpdates = 0;
for (auto const& availableQuery : available)
{
@@ -314,7 +324,7 @@ uint32 UpdateFetcher::Update(bool const redundancyChecks, bool const allowRehash
}
}
- return importedUpdates;
+ return UpdateResult(importedUpdates, countRecentUpdates, countArchivedUpdates);
}
std::string UpdateFetcher::CalculateHash(SQLUpdate const& query) const
@@ -329,7 +339,6 @@ std::string UpdateFetcher::CalculateHash(SQLUpdate const& query) const
uint32 UpdateFetcher::Apply(Path const& path) const
{
using Time = std::chrono::high_resolution_clock;
- using ms = std::chrono::milliseconds;
// Benchmark query speed
auto const begin = Time::now();
@@ -338,7 +347,7 @@ uint32 UpdateFetcher::Apply(Path const& path) const
_applyFile(path);
// Return time the query took to apply
- return std::chrono::duration_cast<ms>(Time::now() - begin).count();
+ return std::chrono::duration_cast<std::chrono::milliseconds>(Time::now() - begin).count();
}
void UpdateFetcher::UpdateEntry(AppliedFileEntry const& entry, uint32 const speed) const
diff --git a/src/server/shared/Updater/UpdateFetcher.h b/src/server/shared/Updater/UpdateFetcher.h
index fa142547873..4ff8c93bc76 100644
--- a/src/server/shared/Updater/UpdateFetcher.h
+++ b/src/server/shared/Updater/UpdateFetcher.h
@@ -35,7 +35,7 @@ public:
std::function<void(Path const& path)> const& applyFile,
std::function<QueryResult(std::string const&)> const& retrieve);
- uint32 Update(bool const redundancyChecks, bool const allowRehash,
+ UpdateResult Update(bool const redundancyChecks, bool const allowRehash,
bool const archivedRedundancy, int32 const cleanDeadReferencesMaxCount) const;
private:
diff --git a/src/server/shared/Utilities/TaskScheduler.cpp b/src/server/shared/Utilities/TaskScheduler.cpp
index 4b261413fd9..04a4071d1f5 100644
--- a/src/server/shared/Utilities/TaskScheduler.cpp
+++ b/src/server/shared/Utilities/TaskScheduler.cpp
@@ -17,16 +17,22 @@
#include "TaskScheduler.h"
-TaskScheduler& TaskScheduler::Update()
+TaskScheduler& TaskScheduler::ClearValidator()
+{
+ _predicate = EmptyValidator;
+ return *this;
+}
+
+TaskScheduler& TaskScheduler::Update(success_t const& callback)
{
_now = clock_t::now();
- Dispatch();
+ Dispatch(callback);
return *this;
}
-TaskScheduler& TaskScheduler::Update(size_t const milliseconds)
+TaskScheduler& TaskScheduler::Update(size_t const milliseconds, success_t const& callback)
{
- return Update(std::chrono::milliseconds(milliseconds));
+ return Update(std::chrono::milliseconds(milliseconds), callback);
}
TaskScheduler& TaskScheduler::Async(std::function<void()> const& callable)
@@ -66,15 +72,26 @@ TaskScheduler& TaskScheduler::InsertTask(TaskContainer task)
return *this;
}
-void TaskScheduler::Dispatch()
+void TaskScheduler::Dispatch(success_t const& callback)
{
+ // If the validation failed abort the dispatching here.
+ if (!_predicate())
+ return;
+
// Process all asyncs
while (!_asyncHolder.empty())
{
_asyncHolder.front()();
_asyncHolder.pop();
+
+ // If the validation failed abort the dispatching here.
+ if (!_predicate())
+ return;
}
+ if (_task_holder.IsEmpty())
+ return;
+
while (!_task_holder.IsEmpty())
{
if (_task_holder.First()->_end > _now)
@@ -86,7 +103,14 @@ void TaskScheduler::Dispatch()
// Invoke the context
context.Invoke();
+
+ // If the validation failed abort the dispatching here.
+ if (!_predicate())
+ return;
}
+
+ // On finish call the final callback
+ callback();
}
void TaskScheduler::TaskQueue::Push(TaskContainer&& task)
diff --git a/src/server/shared/Utilities/TaskScheduler.h b/src/server/shared/Utilities/TaskScheduler.h
index 98e210e55b1..d45835b5f17 100644
--- a/src/server/shared/Utilities/TaskScheduler.h
+++ b/src/server/shared/Utilities/TaskScheduler.h
@@ -60,6 +60,10 @@ class TaskScheduler
typedef uint32 repeated_t;
// Task handle type
typedef std::function<void(TaskContext)> task_handler_t;
+ // Predicate type
+ typedef std::function<bool()> predicate_t;
+ // Success handle type
+ typedef std::function<void()> success_t;
class Task
{
@@ -163,27 +167,57 @@ class TaskScheduler
/// the next update tick.
AsyncHolder _asyncHolder;
+ predicate_t _predicate;
+
+ static bool EmptyValidator()
+ {
+ return true;
+ }
+
+ static void EmptyCallback()
+ {
+ }
+
public:
- TaskScheduler() : self_reference(this, [](TaskScheduler const*) { }),
- _now(clock_t::now()) { }
+ TaskScheduler()
+ : self_reference(this, [](TaskScheduler const*) { }), _now(clock_t::now()), _predicate(EmptyValidator) { }
+
+ template<typename P>
+ TaskScheduler(P&& predicate)
+ : self_reference(this, [](TaskScheduler const*) { }), _now(clock_t::now()), _predicate(std::forward<P>(predicate)) { }
TaskScheduler(TaskScheduler const&) = delete;
TaskScheduler(TaskScheduler&&) = delete;
TaskScheduler& operator= (TaskScheduler const&) = delete;
TaskScheduler& operator= (TaskScheduler&&) = delete;
+ /// Sets a validator which is asked if tasks are allowed to be executed.
+ template<typename P>
+ TaskScheduler& SetValidator(P&& predicate)
+ {
+ _predicate = std::forward<P>(predicate);
+ return *this;
+ }
+
+ /// Clears the validator which is asked if tasks are allowed to be executed.
+ TaskScheduler& ClearValidator();
+
/// Update the scheduler to the current time.
- TaskScheduler& Update();
+ /// Calls the optional callback on successfully finish.
+ TaskScheduler& Update(success_t const& callback = EmptyCallback);
/// Update the scheduler with a difftime in ms.
- TaskScheduler& Update(size_t const milliseconds);
+ /// Calls the optional callback on successfully finish.
+ TaskScheduler& Update(size_t const milliseconds, success_t const& callback = EmptyCallback);
/// Update the scheduler with a difftime.
+ /// Calls the optional callback on successfully finish.
template<class _Rep, class _Period>
- TaskScheduler& Update(std::chrono::duration<_Rep, _Period> const& difftime)
+ TaskScheduler& Update(std::chrono::duration<_Rep, _Period> const& difftime,
+ success_t const& callback = EmptyCallback)
{
_now += difftime;
- Dispatch();
+ Dispatch(callback);
return *this;
}
@@ -370,7 +404,7 @@ private:
}
/// Dispatch remaining tasks
- void Dispatch();
+ void Dispatch(success_t const& callback);
};
class TaskContext