summaryrefslogtreecommitdiff
path: root/indra/llmessage/llavatarnamecache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llmessage/llavatarnamecache.cpp')
-rw-r--r--indra/llmessage/llavatarnamecache.cpp281
1 files changed, 111 insertions, 170 deletions
diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp
index ba1a2a035e..6a287f0cc5 100644
--- a/indra/llmessage/llavatarnamecache.cpp
+++ b/indra/llmessage/llavatarnamecache.cpp
@@ -49,101 +49,22 @@
#include <map>
#include <set>
-namespace LLAvatarNameCache
-{
- use_display_name_signal_t mUseDisplayNamesSignal;
-
- // Cache starts in a paused state until we can determine if the
- // current region supports display names.
- bool sRunning = false;
-
- // Use the People API (modern) for fetching name if true. Use the old legacy protocol if false.
- // For testing, there's a UsePeopleAPI setting that can be flipped (must restart viewer).
- bool sUsePeopleAPI = true;
-
- // Base lookup URL for name service.
- // On simulator, loaded from indra.xml
- // On viewer, usually a simulator capability (at People API team's request)
- // Includes the trailing slash, like "http://pdp60.lindenlab.com:8000/agents/"
- std::string sNameLookupURL;
-
- // Accumulated agent IDs for next query against service
- typedef std::set<LLUUID> ask_queue_t;
- ask_queue_t sAskQueue;
-
- // Agent IDs that have been requested, but with no reply.
- // Maps agent ID to frame time request was made.
- typedef std::map<LLUUID, F64> pending_queue_t;
- pending_queue_t sPendingQueue;
-
- // Callbacks to fire when we received a name.
- // May have multiple callbacks for a single ID, which are
- // represented as multiple slots bound to the signal.
- // Avoid copying signals via pointers.
- typedef std::map<LLUUID, callback_signal_t*> signal_map_t;
- signal_map_t sSignalMap;
-
- // The cache at last, i.e. avatar names we know about.
- typedef std::map<LLUUID, LLAvatarName> cache_t;
- cache_t sCache;
-
- // Send bulk lookup requests a few times a second at most.
- // Only need per-frame timing resolution.
- LLFrameTimer sRequestTimer;
-
- // Maximum time an unrefreshed cache entry is allowed.
- const F64 MAX_UNREFRESHED_TIME = 20.0 * 60.0;
-
- // Time when unrefreshed cached names were checked last.
- static F64 sLastExpireCheck;
-
- // Time-to-live for a temp cache entry.
- const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0;
-
- LLCore::HttpRequest::ptr_t sHttpRequest;
- LLCore::HttpHeaders::ptr_t sHttpHeaders;
- LLCore::HttpOptions::ptr_t sHttpOptions;
- LLCore::HttpRequest::policy_t sHttpPolicy;
- LLCore::HttpRequest::priority_t sHttpPriority;
-
- //-----------------------------------------------------------------------
- // Internal methods
- //-----------------------------------------------------------------------
-
- // Handle name response off network.
- void processName(const LLUUID& agent_id,
- const LLAvatarName& av_name);
-
- void requestNamesViaCapability();
-
- // Legacy name system callbacks
- void legacyNameCallback(const LLUUID& agent_id,
- const std::string& full_name,
- bool is_group);
- void legacyNameFetch(const LLUUID& agent_id,
- const std::string& full_name,
- bool is_group);
-
- void requestNamesViaLegacy();
-
- // Do a single callback to a given slot
- void fireSignal(const LLUUID& agent_id,
- const callback_slot_t& slot,
- const LLAvatarName& av_name);
-
- // Is a request in-flight over the network?
- bool isRequestPending(const LLUUID& agent_id);
- // Erase expired names from cache
- void eraseUnrefreshed();
+// Time-to-live for a temp cache entry.
+const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0;
+// Maximum time an unrefreshed cache entry is allowed.
+const F64 MAX_UNREFRESHED_TIME = 20.0 * 60.0;
- bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
+// Send bulk lookup requests a few times a second at most.
+// Only need per-frame timing resolution.
+static LLFrameTimer sRequestTimer;
- // This is a coroutine.
- void requestAvatarNameCache_(std::string url, std::vector<LLUUID> agentIds);
-
- void handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult);
-}
+// static to avoid unnessesary dependencies
+LLCore::HttpRequest::ptr_t sHttpRequest;
+LLCore::HttpHeaders::ptr_t sHttpHeaders;
+LLCore::HttpOptions::ptr_t sHttpOptions;
+LLCore::HttpRequest::policy_t sHttpPolicy;
+LLCore::HttpRequest::priority_t sHttpPriority;
/* Sample response:
<?xml version="1.0"?>
@@ -187,6 +108,30 @@ namespace LLAvatarNameCache
// Coroutine for sending and processing avatar name cache requests.
// Do not call directly. See documentation in lleventcoro.h and llcoro.h for
// further explanation.
+
+LLAvatarNameCache::LLAvatarNameCache()
+{
+ // Will be set to running later
+ // For now fail immediate lookups and query async ones.
+ mRunning = false;
+
+ mUsePeopleAPI = true;
+
+ sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest());
+ sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
+ sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions());
+ sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID;
+ sHttpPriority = 0;
+}
+
+LLAvatarNameCache::~LLAvatarNameCache()
+{
+ sHttpRequest.reset();
+ sHttpHeaders.reset();
+ sHttpOptions.reset();
+ mCache.clear();
+}
+
void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLUUID> agentIds)
{
LL_DEBUGS("AvNameCache") << "Entering coroutine " << LLCoros::instance().getName()
@@ -205,7 +150,7 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLU
{
bool success = true;
- LLCoreHttpUtil::HttpCoroutineAdapter httpAdapter("NameCache", LLAvatarNameCache::sHttpPolicy);
+ LLCoreHttpUtil::HttpCoroutineAdapter httpAdapter("NameCache", sHttpPolicy);
LLSD results = httpAdapter.getAndSuspend(sHttpRequest, url);
LL_DEBUGS() << results << LL_ENDL;
@@ -233,12 +178,12 @@ void LLAvatarNameCache::requestAvatarNameCache_(std::string url, std::vector<LLU
for ( ; it != agentIds.end(); ++it)
{
const LLUUID& agent_id = *it;
- LLAvatarNameCache::handleAgentError(agent_id);
+ LLAvatarNameCache::getInstance()->handleAgentError(agent_id);
}
return;
}
- LLAvatarNameCache::handleAvNameCacheSuccess(results, httpResults);
+ LLAvatarNameCache::getInstance()->handleAvNameCacheSuccess(results, httpResults);
}
catch (...)
@@ -300,15 +245,15 @@ void LLAvatarNameCache::handleAvNameCacheSuccess(const LLSD &data, const LLSD &h
}
}
LL_DEBUGS("AvNameCache") << "LLAvatarNameResponder::result "
- << LLAvatarNameCache::sCache.size() << " cached names"
+ << LLAvatarNameCache::mCache.size() << " cached names"
<< LL_ENDL;
}
// Provide some fallback for agents that return errors
void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
{
- std::map<LLUUID,LLAvatarName>::iterator existing = sCache.find(agent_id);
- if (existing == sCache.end())
+ std::map<LLUUID,LLAvatarName>::iterator existing = mCache.find(agent_id);
+ if (existing == mCache.end())
{
// there is no existing cache entry, so make a temporary name from legacy
LL_WARNS("AvNameCache") << "LLAvatarNameCache get legacy for agent "
@@ -322,7 +267,7 @@ void LLAvatarNameCache::handleAgentError(const LLUUID& agent_id)
// been returned by the get method, there is no need to signal anyone
// Clear this agent from the pending list
- LLAvatarNameCache::sPendingQueue.erase(agent_id);
+ LLAvatarNameCache::mPendingQueue.erase(agent_id);
LLAvatarName& av_name = existing->second;
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent " << agent_id << LL_ENDL;
@@ -341,19 +286,19 @@ void LLAvatarNameCache::processName(const LLUUID& agent_id, const LLAvatarName&
}
// Add to the cache
- sCache[agent_id] = av_name;
+ mCache[agent_id] = av_name;
// Suppress request from the queue
- sPendingQueue.erase(agent_id);
+ mPendingQueue.erase(agent_id);
// Signal everyone waiting on this name
- signal_map_t::iterator sig_it = sSignalMap.find(agent_id);
- if (sig_it != sSignalMap.end())
+ signal_map_t::iterator sig_it = mSignalMap.find(agent_id);
+ if (sig_it != mSignalMap.end())
{
callback_signal_t* signal = sig_it->second;
(*signal)(agent_id, av_name);
- sSignalMap.erase(agent_id);
+ mSignalMap.erase(agent_id);
delete signal;
signal = NULL;
@@ -379,16 +324,16 @@ void LLAvatarNameCache::requestNamesViaCapability()
U32 ids = 0;
ask_queue_t::const_iterator it;
- while(!sAskQueue.empty())
+ while(!mAskQueue.empty())
{
- it = sAskQueue.begin();
+ it = mAskQueue.begin();
LLUUID agent_id = *it;
- sAskQueue.erase(it);
+ mAskQueue.erase(it);
if (url.empty())
{
// ...starting new request
- url += sNameLookupURL;
+ url += mNameLookupURL;
url += "?ids=";
ids = 1;
}
@@ -402,7 +347,7 @@ void LLAvatarNameCache::requestNamesViaCapability()
agent_ids.push_back(agent_id);
// mark request as pending
- sPendingQueue[agent_id] = now;
+ mPendingQueue[agent_id] = now;
if (url.size() > NAME_URL_SEND_THRESHOLD)
{
@@ -432,7 +377,7 @@ void LLAvatarNameCache::legacyNameCallback(const LLUUID& agent_id,
// Retrieve the name and set it to never (or almost never...) expire: when we are using the legacy
// protocol, we do not get an expiration date for each name and there's no reason to ask the
// data again and again so we set the expiration time to the largest value admissible.
- std::map<LLUUID,LLAvatarName>::iterator av_record = sCache.find(agent_id);
+ std::map<LLUUID,LLAvatarName>::iterator av_record = LLAvatarNameCache::getInstance()->mCache.find(agent_id);
LLAvatarName& av_name = av_record->second;
av_name.setExpires(MAX_UNREFRESHED_TIME);
}
@@ -451,7 +396,7 @@ void LLAvatarNameCache::legacyNameFetch(const LLUUID& agent_id,
av_name.fromString(full_name);
// Add to cache: we're still using the new cache even if we're using the old (legacy) protocol.
- processName(agent_id, av_name);
+ LLAvatarNameCache::getInstance()->processName(agent_id, av_name);
}
void LLAvatarNameCache::requestNamesViaLegacy()
@@ -460,15 +405,15 @@ void LLAvatarNameCache::requestNamesViaLegacy()
F64 now = LLFrameTimer::getTotalSeconds();
std::string full_name;
ask_queue_t::const_iterator it;
- for (S32 requests = 0; !sAskQueue.empty() && requests < MAX_REQUESTS; ++requests)
+ for (S32 requests = 0; !mAskQueue.empty() && requests < MAX_REQUESTS; ++requests)
{
- it = sAskQueue.begin();
+ it = mAskQueue.begin();
LLUUID agent_id = *it;
- sAskQueue.erase(it);
+ mAskQueue.erase(it);
// Mark as pending first, just in case the callback is immediately
// invoked below. This should never happen in practice.
- sPendingQueue[agent_id] = now;
+ mPendingQueue[agent_id] = now;
LL_DEBUGS("AvNameCache") << "agent " << agent_id << LL_ENDL;
@@ -477,26 +422,6 @@ void LLAvatarNameCache::requestNamesViaLegacy()
}
}
-void LLAvatarNameCache::initClass(bool running, bool usePeopleAPI)
-{
- sRunning = running;
- sUsePeopleAPI = usePeopleAPI;
-
- sHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest());
- sHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
- sHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions());
- sHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID;
- sHttpPriority = 0;
-}
-
-void LLAvatarNameCache::cleanupClass()
-{
- sHttpRequest.reset();
- sHttpHeaders.reset();
- sHttpOptions.reset();
- sCache.clear();
-}
-
bool LLAvatarNameCache::importFile(std::istream& istr)
{
LLSD data;
@@ -517,9 +442,9 @@ bool LLAvatarNameCache::importFile(std::istream& istr)
{
agent_id.set(it->first);
av_name.fromLLSD( it->second );
- sCache[agent_id] = av_name;
+ mCache[agent_id] = av_name;
}
- LL_INFOS("AvNameCache") << "LLAvatarNameCache loaded " << sCache.size() << LL_ENDL;
+ LL_INFOS("AvNameCache") << "LLAvatarNameCache loaded " << mCache.size() << LL_ENDL;
// Some entries may have expired since the cache was stored,
// but they will be flushed in the first call to eraseUnrefreshed
// from LLAvatarNameResponder::idle
@@ -531,9 +456,9 @@ void LLAvatarNameCache::exportFile(std::ostream& ostr)
{
LLSD agents;
F64 max_unrefreshed = LLFrameTimer::getTotalSeconds() - MAX_UNREFRESHED_TIME;
- LL_INFOS("AvNameCache") << "LLAvatarNameCache at exit cache has " << sCache.size() << LL_ENDL;
- cache_t::const_iterator it = sCache.begin();
- for ( ; it != sCache.end(); ++it)
+ LL_INFOS("AvNameCache") << "LLAvatarNameCache at exit cache has " << mCache.size() << LL_ENDL;
+ cache_t::const_iterator it = mCache.begin();
+ for ( ; it != mCache.end(); ++it)
{
const LLUUID& agent_id = it->first;
const LLAvatarName& av_name = it->second;
@@ -552,23 +477,28 @@ void LLAvatarNameCache::exportFile(std::ostream& ostr)
void LLAvatarNameCache::setNameLookupURL(const std::string& name_lookup_url)
{
- sNameLookupURL = name_lookup_url;
+ mNameLookupURL = name_lookup_url;
}
bool LLAvatarNameCache::hasNameLookupURL()
{
- return !sNameLookupURL.empty();
+ return !mNameLookupURL.empty();
+}
+
+void LLAvatarNameCache::setUsePeopleAPI(bool use_api)
+{
+ mUsePeopleAPI = use_api;
}
bool LLAvatarNameCache::usePeopleAPI()
{
- return hasNameLookupURL() && sUsePeopleAPI;
+ return hasNameLookupURL() && mUsePeopleAPI;
}
void LLAvatarNameCache::idle()
{
// By convention, start running at first idle() call
- sRunning = true;
+ mRunning = true;
// *TODO: Possibly re-enabled this based on People API load measurements
// 100 ms is the threshold for "user speed" operations, so we can
@@ -579,7 +509,7 @@ void LLAvatarNameCache::idle()
return;
}
- if (!sAskQueue.empty())
+ if (!mAskQueue.empty())
{
if (usePeopleAPI())
{
@@ -592,7 +522,7 @@ void LLAvatarNameCache::idle()
}
}
- if (sAskQueue.empty())
+ if (mAskQueue.empty())
{
// cleared the list, reset the request timer.
sRequestTimer.resetWithExpiry(SECS_BETWEEN_REQUESTS);
@@ -607,8 +537,8 @@ bool LLAvatarNameCache::isRequestPending(const LLUUID& agent_id)
bool isPending = false;
const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0;
- pending_queue_t::const_iterator it = sPendingQueue.find(agent_id);
- if (it != sPendingQueue.end())
+ pending_queue_t::const_iterator it = mPendingQueue.find(agent_id);
+ if (it != mPendingQueue.end())
{
// in the list of requests in flight, retry if too old
F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS;
@@ -622,11 +552,11 @@ void LLAvatarNameCache::eraseUnrefreshed()
F64 now = LLFrameTimer::getTotalSeconds();
F64 max_unrefreshed = now - MAX_UNREFRESHED_TIME;
- if (!sLastExpireCheck || sLastExpireCheck < max_unrefreshed)
+ if (!mLastExpireCheck || mLastExpireCheck < max_unrefreshed)
{
- sLastExpireCheck = now;
+ mLastExpireCheck = now;
S32 expired = 0;
- for (cache_t::iterator it = sCache.begin(); it != sCache.end();)
+ for (cache_t::iterator it = mCache.begin(); it != mCache.end();)
{
const LLAvatarName& av_name = it->second;
if (av_name.mExpires < max_unrefreshed)
@@ -635,7 +565,7 @@ void LLAvatarNameCache::eraseUnrefreshed()
<< " user '" << av_name.getAccountName() << "' "
<< "expired " << now - av_name.mExpires << " secs ago"
<< LL_ENDL;
- sCache.erase(it++);
+ mCache.erase(it++);
expired++;
}
else
@@ -644,19 +574,24 @@ void LLAvatarNameCache::eraseUnrefreshed()
}
}
LL_INFOS("AvNameCache") << "LLAvatarNameCache expired " << expired << " cached avatar names, "
- << sCache.size() << " remaining" << LL_ENDL;
+ << mCache.size() << " remaining" << LL_ENDL;
}
}
+//static, wrapper
+bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
+{
+ return LLAvatarNameCache::getInstance()->getName(agent_id, av_name);
+}
// fills in av_name if it has it in the cache, even if expired (can check expiry time)
// returns bool specifying if av_name was filled, false otherwise
-bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
+bool LLAvatarNameCache::getName(const LLUUID& agent_id, LLAvatarName *av_name)
{
- if (sRunning)
+ if (mRunning)
{
// ...only do immediate lookups when cache is running
- std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
- if (it != sCache.end())
+ std::map<LLUUID,LLAvatarName>::iterator it = mCache.find(agent_id);
+ if (it != mCache.end())
{
*av_name = it->second;
@@ -667,7 +602,7 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
{
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache refresh agent " << agent_id
<< LL_ENDL;
- sAskQueue.insert(agent_id);
+ mAskQueue.insert(agent_id);
}
}
@@ -678,7 +613,7 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
if (!isRequestPending(agent_id))
{
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache queue request for agent " << agent_id << LL_ENDL;
- sAskQueue.insert(agent_id);
+ mAskQueue.insert(agent_id);
}
return false;
@@ -693,15 +628,21 @@ void LLAvatarNameCache::fireSignal(const LLUUID& agent_id,
signal(agent_id, av_name);
}
+// static, wrapper
LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& agent_id, callback_slot_t slot)
{
+ return LLAvatarNameCache::getInstance()->getNameCallback(agent_id, slot);
+}
+
+LLAvatarNameCache::callback_connection_t LLAvatarNameCache::getNameCallback(const LLUUID& agent_id, callback_slot_t slot)
+{
callback_connection_t connection;
- if (sRunning)
+ if (mRunning)
{
// ...only do immediate lookups when cache is running
- std::map<LLUUID,LLAvatarName>::iterator it = sCache.find(agent_id);
- if (it != sCache.end())
+ std::map<LLUUID,LLAvatarName>::iterator it = mCache.find(agent_id);
+ if (it != mCache.end())
{
const LLAvatarName& av_name = it->second;
@@ -717,17 +658,17 @@ LLAvatarNameCache::callback_connection_t LLAvatarNameCache::get(const LLUUID& ag
// schedule a request
if (!isRequestPending(agent_id))
{
- sAskQueue.insert(agent_id);
+ mAskQueue.insert(agent_id);
}
// always store additional callback, even if request is pending
- signal_map_t::iterator sig_it = sSignalMap.find(agent_id);
- if (sig_it == sSignalMap.end())
+ signal_map_t::iterator sig_it = mSignalMap.find(agent_id);
+ if (sig_it == mSignalMap.end())
{
// ...new callback for this id
callback_signal_t* signal = new callback_signal_t();
connection = signal->connect(slot);
- sSignalMap[agent_id] = signal;
+ mSignalMap[agent_id] = signal;
}
else
{
@@ -760,20 +701,20 @@ void LLAvatarNameCache::setUseUsernames(bool use)
void LLAvatarNameCache::erase(const LLUUID& agent_id)
{
- sCache.erase(agent_id);
+ mCache.erase(agent_id);
}
void LLAvatarNameCache::insert(const LLUUID& agent_id, const LLAvatarName& av_name)
{
// *TODO: update timestamp if zero?
- sCache[agent_id] = av_name;
+ mCache[agent_id] = av_name;
}
LLUUID LLAvatarNameCache::findIdByName(const std::string& name)
{
std::map<LLUUID, LLAvatarName>::iterator it;
- std::map<LLUUID, LLAvatarName>::iterator end = sCache.end();
- for (it = sCache.begin(); it != end; ++it)
+ std::map<LLUUID, LLAvatarName>::iterator end = mCache.end();
+ for (it = mCache.begin(); it != end; ++it)
{
if (it->second.getUserName() == name)
{