cMojangAPI: Added periodical refreshes.
This commit is contained in:
parent
89713e23e4
commit
3d2d8a096b
@ -11,6 +11,8 @@
|
|||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
#include "PolarSSL++/BlockingSslClientSocket.h"
|
#include "PolarSSL++/BlockingSslClientSocket.h"
|
||||||
#include "../RankManager.h"
|
#include "../RankManager.h"
|
||||||
|
#include "../OSSupport/IsThread.h"
|
||||||
|
#include "../Root.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -151,6 +153,41 @@ cMojangAPI::sProfile::sProfile(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cMojangAPI::cUpdateThread:
|
||||||
|
|
||||||
|
class cMojangAPI::cUpdateThread :
|
||||||
|
public cIsThread
|
||||||
|
{
|
||||||
|
typedef cIsThread super;
|
||||||
|
public:
|
||||||
|
cUpdateThread() :
|
||||||
|
super("cMojangAPI::cUpdateThread")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
~cUpdateThread()
|
||||||
|
{
|
||||||
|
m_evtNotify.Set();
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cEvent m_evtNotify;
|
||||||
|
|
||||||
|
virtual void Execute(void) override
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
cRoot::Get()->GetMojangAPI().Update();
|
||||||
|
} while (!m_evtNotify.Wait(60 * 60 * 1000)); // Repeat every 60 minutes
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// cMojangAPI:
|
// cMojangAPI:
|
||||||
|
|
||||||
@ -159,7 +196,8 @@ cMojangAPI::cMojangAPI(void) :
|
|||||||
m_NameToUUIDAddress(DEFAULT_NAME_TO_UUID_ADDRESS),
|
m_NameToUUIDAddress(DEFAULT_NAME_TO_UUID_ADDRESS),
|
||||||
m_UUIDToProfileServer(DEFAULT_UUID_TO_PROFILE_SERVER),
|
m_UUIDToProfileServer(DEFAULT_UUID_TO_PROFILE_SERVER),
|
||||||
m_UUIDToProfileAddress(DEFAULT_UUID_TO_PROFILE_ADDRESS),
|
m_UUIDToProfileAddress(DEFAULT_UUID_TO_PROFILE_ADDRESS),
|
||||||
m_RankMgr(NULL)
|
m_RankMgr(NULL),
|
||||||
|
m_UpdateThread(new cUpdateThread())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,6 +221,7 @@ void cMojangAPI::Start(cIniFile & a_SettingsIni)
|
|||||||
m_UUIDToProfileServer = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileServer", DEFAULT_UUID_TO_PROFILE_SERVER);
|
m_UUIDToProfileServer = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileServer", DEFAULT_UUID_TO_PROFILE_SERVER);
|
||||||
m_UUIDToProfileAddress = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileAddress", DEFAULT_UUID_TO_PROFILE_ADDRESS);
|
m_UUIDToProfileAddress = a_SettingsIni.GetValueSet("MojangAPI", "UUIDToProfileAddress", DEFAULT_UUID_TO_PROFILE_ADDRESS);
|
||||||
LoadCachesFromDisk();
|
LoadCachesFromDisk();
|
||||||
|
m_UpdateThread->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -465,21 +504,7 @@ void cMojangAPI::LoadCachesFromDisk(void)
|
|||||||
db.exec("CREATE TABLE IF NOT EXISTS PlayerNameToUUID (PlayerName, UUID, DateTime)");
|
db.exec("CREATE TABLE IF NOT EXISTS PlayerNameToUUID (PlayerName, UUID, DateTime)");
|
||||||
db.exec("CREATE TABLE IF NOT EXISTS UUIDToProfile (UUID, PlayerName, Textures, TexturesSignature, DateTime)");
|
db.exec("CREATE TABLE IF NOT EXISTS UUIDToProfile (UUID, PlayerName, Textures, TexturesSignature, DateTime)");
|
||||||
|
|
||||||
// Clean up old entries:
|
// Retrieve all entries:
|
||||||
{
|
|
||||||
SQLite::Statement stmt(db, "DELETE FROM PlayerNameToUUID WHERE DateTime < ?");
|
|
||||||
Int64 LimitDateTime = time(NULL) - MAX_AGE;
|
|
||||||
stmt.bind(1, LimitDateTime);
|
|
||||||
stmt.exec();
|
|
||||||
}
|
|
||||||
{
|
|
||||||
SQLite::Statement stmt(db, "DELETE FROM UUIDToProfile WHERE DateTime < ?");
|
|
||||||
Int64 LimitDateTime = time(NULL) - MAX_AGE;
|
|
||||||
stmt.bind(1, LimitDateTime);
|
|
||||||
stmt.exec();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve all remaining entries:
|
|
||||||
{
|
{
|
||||||
SQLite::Statement stmt(db, "SELECT PlayerName, UUID, DateTime FROM PlayerNameToUUID");
|
SQLite::Statement stmt(db, "SELECT PlayerName, UUID, DateTime FROM PlayerNameToUUID");
|
||||||
while (stmt.executeStep())
|
while (stmt.executeStep())
|
||||||
@ -596,18 +621,27 @@ void cMojangAPI::CacheNamesToUUIDs(const AStringVector & a_PlayerNames)
|
|||||||
} // for itr - a_PlayerNames[]
|
} // for itr - a_PlayerNames[]
|
||||||
} // Lock(m_CSNameToUUID)
|
} // Lock(m_CSNameToUUID)
|
||||||
|
|
||||||
while (!NamesToQuery.empty())
|
QueryNamesToUUIDs(NamesToQuery);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cMojangAPI::QueryNamesToUUIDs(AStringVector & a_NamesToQuery)
|
||||||
|
{
|
||||||
|
while (!a_NamesToQuery.empty())
|
||||||
{
|
{
|
||||||
// Create the request body - a JSON containing up to MAX_PER_QUERY playernames:
|
// Create the request body - a JSON containing up to MAX_PER_QUERY playernames:
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
int Count = 0;
|
int Count = 0;
|
||||||
AStringVector::iterator itr = NamesToQuery.begin(), end = NamesToQuery.end();
|
AStringVector::iterator itr = a_NamesToQuery.begin(), end = a_NamesToQuery.end();
|
||||||
for (; (itr != end) && (Count < MAX_PER_QUERY); ++itr, ++Count)
|
for (; (itr != end) && (Count < MAX_PER_QUERY); ++itr, ++Count)
|
||||||
{
|
{
|
||||||
Json::Value req(*itr);
|
Json::Value req(*itr);
|
||||||
root.append(req);
|
root.append(req);
|
||||||
} // for itr - a_PlayerNames[]
|
} // for itr - a_PlayerNames[]
|
||||||
NamesToQuery.erase(NamesToQuery.begin(), itr);
|
a_NamesToQuery.erase(a_NamesToQuery.begin(), itr);
|
||||||
Json::FastWriter Writer;
|
Json::FastWriter Writer;
|
||||||
AString RequestBody = Writer.write(root);
|
AString RequestBody = Writer.write(root);
|
||||||
|
|
||||||
@ -705,12 +739,22 @@ void cMojangAPI::CacheUUIDToProfile(const AString & a_UUID)
|
|||||||
|
|
||||||
// Check if already present:
|
// Check if already present:
|
||||||
{
|
{
|
||||||
|
cCSLock Lock(m_CSUUIDToProfile);
|
||||||
if (m_UUIDToProfile.find(a_UUID) != m_UUIDToProfile.end())
|
if (m_UUIDToProfile.find(a_UUID) != m_UUIDToProfile.end())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QueryUUIDToProfile(a_UUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cMojangAPI::QueryUUIDToProfile(const AString & a_UUID)
|
||||||
|
{
|
||||||
// Create the request address:
|
// Create the request address:
|
||||||
AString Address = m_UUIDToProfileAddress;
|
AString Address = m_UUIDToProfileAddress;
|
||||||
ReplaceString(Address, "%UUID%", a_UUID);
|
ReplaceString(Address, "%UUID%", a_UUID);
|
||||||
@ -817,3 +861,51 @@ void cMojangAPI::NotifyNameUUID(const AString & a_PlayerName, const AString & a_
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cMojangAPI::Update(void)
|
||||||
|
{
|
||||||
|
Int64 LimitDateTime = time(NULL) - MAX_AGE;
|
||||||
|
|
||||||
|
// Re-query all playernames that are stale:
|
||||||
|
AStringVector PlayerNames;
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CSNameToUUID);
|
||||||
|
for (cProfileMap::const_iterator itr = m_NameToUUID.begin(), end = m_NameToUUID.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
if (itr->second.m_DateTime < LimitDateTime)
|
||||||
|
{
|
||||||
|
PlayerNames.push_back(itr->first);
|
||||||
|
}
|
||||||
|
} // for itr - m_NameToUUID[]
|
||||||
|
}
|
||||||
|
if (!PlayerNames.empty())
|
||||||
|
{
|
||||||
|
LOG("cMojangAPI: Updating name-to-uuid cache for %u names", (unsigned)PlayerNames.size());
|
||||||
|
QueryNamesToUUIDs(PlayerNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-query all profiles that are stale:
|
||||||
|
AStringVector ProfileUUIDs;
|
||||||
|
{
|
||||||
|
cCSLock Lock(m_CSUUIDToProfile);
|
||||||
|
for (cProfileMap::const_iterator itr = m_UUIDToProfile.begin(), end = m_UUIDToProfile.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
if (itr->second.m_DateTime < LimitDateTime)
|
||||||
|
{
|
||||||
|
ProfileUUIDs.push_back(itr->first);
|
||||||
|
}
|
||||||
|
} // for itr - m_UUIDToProfile[]
|
||||||
|
}
|
||||||
|
if (!ProfileUUIDs.empty())
|
||||||
|
{
|
||||||
|
LOG("cMojangAPI: Updating uuid-to-profile cache for %u uuids", (unsigned)ProfileUUIDs.size());
|
||||||
|
for (AStringVector::const_iterator itr = ProfileUUIDs.begin(), end = ProfileUUIDs.end(); itr != end; ++itr)
|
||||||
|
{
|
||||||
|
QueryUUIDToProfile(*itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,6 +93,10 @@ public:
|
|||||||
void SetRankManager(cRankManager * a_RankManager) { m_RankMgr = a_RankManager; }
|
void SetRankManager(cRankManager * a_RankManager) { m_RankMgr = a_RankManager; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/** The thread that periodically checks for stale data and re-queries it from the server. */
|
||||||
|
class cUpdateThread;
|
||||||
|
|
||||||
|
|
||||||
/** Holds data for a single player profile. */
|
/** Holds data for a single player profile. */
|
||||||
struct sProfile
|
struct sProfile
|
||||||
{
|
{
|
||||||
@ -177,6 +181,9 @@ protected:
|
|||||||
|
|
||||||
/** Protects m_RankMgr agains simultaneous multi-threaded access. */
|
/** Protects m_RankMgr agains simultaneous multi-threaded access. */
|
||||||
cCriticalSection m_CSRankMgr;
|
cCriticalSection m_CSRankMgr;
|
||||||
|
|
||||||
|
/** The thread that periodically updates the stale data in the DB from the Mojang servers. */
|
||||||
|
SharedPtr<cUpdateThread> m_UpdateThread;
|
||||||
|
|
||||||
|
|
||||||
/** Loads the caches from a disk storage. */
|
/** Loads the caches from a disk storage. */
|
||||||
@ -189,15 +196,29 @@ protected:
|
|||||||
Names that are not valid are not added into the cache.
|
Names that are not valid are not added into the cache.
|
||||||
ASSUMEs that a_PlayerNames contains lowercased player names. */
|
ASSUMEs that a_PlayerNames contains lowercased player names. */
|
||||||
void CacheNamesToUUIDs(const AStringVector & a_PlayerNames);
|
void CacheNamesToUUIDs(const AStringVector & a_PlayerNames);
|
||||||
|
|
||||||
|
/** Queries all the specified names and stores them into the m_PlayerNameToUUID cache.
|
||||||
|
Names that are not valid are not added into the cache.
|
||||||
|
ASSUMEs that a_PlayerNames contans lowercased player names.
|
||||||
|
For performance reasons takes a non-const reference and modifies the list given to it, until empty. */
|
||||||
|
void QueryNamesToUUIDs(AStringVector & a_PlayerNames);
|
||||||
|
|
||||||
/** Makes sure the specified UUID is in the m_UUIDToProfile cache. If missing, downloads it from Mojang API servers.
|
/** Makes sure the specified UUID is in the m_UUIDToProfile cache. If missing, downloads it from Mojang API servers.
|
||||||
UUIDs that are not valid will not be added into the cache.
|
UUIDs that are not valid will not be added into the cache.
|
||||||
ASSUMEs that a_UUID is a lowercased short UUID. */
|
ASSUMEs that a_UUID is a lowercased short UUID. */
|
||||||
void CacheUUIDToProfile(const AString & a_UUID);
|
void CacheUUIDToProfile(const AString & a_UUID);
|
||||||
|
|
||||||
|
/** Queries the specified UUID's profile and stores it in the m_UUIDToProfile cache. If already present, updates the cache entry.
|
||||||
|
UUIDs that are not valid will not be added into the cache.
|
||||||
|
ASSUMEs that a_UUID is a lowercased short UUID. */
|
||||||
|
void QueryUUIDToProfile(const AString & a_UUID);
|
||||||
|
|
||||||
/** Called for each name-uuid pairing that is discovered.
|
/** Called for each name-uuid pairing that is discovered.
|
||||||
If assigned, notifies the m_RankManager of the event. */
|
If assigned, notifies the m_RankManager of the event. */
|
||||||
void NotifyNameUUID(const AString & a_PlayerName, const AString & a_PlayerUUID);
|
void NotifyNameUUID(const AString & a_PlayerName, const AString & a_PlayerUUID);
|
||||||
|
|
||||||
|
/** Updates the stale values in the DB from the Mojang servers. Called from the cUpdateThread, blocks on the HTTPS API calls. */
|
||||||
|
void Update(void);
|
||||||
} ; // tolua_export
|
} ; // tolua_export
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user