diff options
-rw-r--r-- | indra/llmessage/llavatarnamecache.cpp | 281 | ||||
-rw-r--r-- | indra/llmessage/llavatarnamecache.h | 98 | ||||
-rw-r--r-- | indra/newview/llappviewer.cpp | 13 | ||||
-rw-r--r-- | indra/newview/llavatarlist.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llfloaterconversationpreview.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llfloaterimcontainer.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llfloaterimnearbychat.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llfloaterpreference.cpp | 4 | ||||
-rw-r--r-- | indra/newview/llimprocessing.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llimview.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llnotificationhandlerutil.cpp | 2 | ||||
-rw-r--r-- | indra/newview/llstartup.cpp | 9 | ||||
-rw-r--r-- | indra/newview/llviewermenu.cpp | 1 |
13 files changed, 220 insertions, 202 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) { diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index 63e067c939..ba89d569f3 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -29,21 +29,20 @@ #define LLAVATARNAMECACHE_H #include "llavatarname.h" // for convenience +#include "llsingleton.h" #include <boost/signals2.hpp> +#include <set> class LLSD; class LLUUID; -namespace LLAvatarNameCache +class LLAvatarNameCache : public LLSingleton<LLAvatarNameCache> { + LLSINGLETON(LLAvatarNameCache); + ~LLAvatarNameCache(); +public: typedef boost::signals2::signal<void (void)> use_display_name_signal_t; - // Until the cache is set running, immediate lookups will fail and - // async lookups will be queued. This allows us to block requests - // until we know if the first region supports display names. - void initClass(bool running, bool usePeopleAPI); - void cleanupClass(); - // Import/export the name cache to file. bool importFile(std::istream& istr); void exportFile(std::ostream& ostr); @@ -55,6 +54,7 @@ namespace LLAvatarNameCache // Do we have a valid lookup URL, i.e. are we trying to use the // more recent display name lookup system? bool hasNameLookupURL(); + void setUsePeopleAPI(bool use_api); bool usePeopleAPI(); // Periodically makes a batch request for display names not already in @@ -63,7 +63,8 @@ namespace LLAvatarNameCache // If name is in cache, returns true and fills in provided LLAvatarName // otherwise returns false. - bool get(const LLUUID& agent_id, LLAvatarName *av_name); + static bool get(const LLUUID& agent_id, LLAvatarName *av_name); + bool getName(const LLUUID& agent_id, LLAvatarName *av_name); // Callback types for get() below typedef boost::signals2::signal< @@ -74,7 +75,8 @@ namespace LLAvatarNameCache // Fetches name information and calls callbacks. // If name information is in cache, callbacks will be called immediately. - callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot); + static callback_connection_t get(const LLUUID& agent_id, callback_slot_t slot); + callback_connection_t getNameCallback(const LLUUID& agent_id, callback_slot_t slot); // Set display name: flips the switch and triggers the callbacks. void setUseDisplayNames(bool use); @@ -100,7 +102,83 @@ namespace LLAvatarNameCache F64 nameExpirationFromHeaders(const LLSD& headers); void addUseDisplayNamesCallback(const use_display_name_signal_t::slot_type& cb); -} + +private: + // Handle name response off network. + void processName(const LLUUID& agent_id, + const LLAvatarName& av_name); + + void requestNamesViaCapability(); + + // Legacy name system callbacks + static void legacyNameCallback(const LLUUID& agent_id, + const std::string& full_name, + bool is_group); + static 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(); + + bool expirationFromCacheControl(const LLSD& headers, F64 *expires); + + // This is a coroutine. + static void requestAvatarNameCache_(std::string url, std::vector<LLUUID> agentIds); + + void handleAvNameCacheSuccess(const LLSD &data, const LLSD &httpResult); + +private: + + use_display_name_signal_t mUseDisplayNamesSignal; + + // Cache starts in a paused state until we can determine if the + // current region supports display names. + bool mRunning; + + // 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 mUsePeopleAPI; + + // 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 mNameLookupURL; + + // Accumulated agent IDs for next query against service + typedef std::set<LLUUID> ask_queue_t; + ask_queue_t mAskQueue; + + // 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 mPendingQueue; + + // 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 mSignalMap; + + // The cache at last, i.e. avatar names we know about. + typedef std::map<LLUUID, LLAvatarName> cache_t; + cache_t mCache; + + // Time when unrefreshed cached names were checked last. + F64 mLastExpireCheck; +}; // Parse a cache-control header to get the max-age delta-seconds. // Returns true if header has max-age param and it parses correctly. diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 151039acce..823ded7a50 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -4509,7 +4509,7 @@ void LLAppViewer::loadNameCache() llifstream name_cache_stream(filename.c_str()); if(name_cache_stream.is_open()) { - if ( ! LLAvatarNameCache::importFile(name_cache_stream)) + if ( ! LLAvatarNameCache::getInstance()->importFile(name_cache_stream)) { LL_WARNS("AppInit") << "removing invalid '" << filename << "'" << LL_ENDL; name_cache_stream.close(); @@ -4536,7 +4536,7 @@ void LLAppViewer::saveNameCache() llofstream name_cache_stream(filename.c_str()); if(name_cache_stream.is_open()) { - LLAvatarNameCache::exportFile(name_cache_stream); + LLAvatarNameCache::getInstance()->exportFile(name_cache_stream); } // real names cache @@ -5143,7 +5143,8 @@ void LLAppViewer::idleNameCache() // granted to neighbor regions before the main agent gets there. Can't // do it in the move-into-region code because cap not guaranteed to be // granted yet, for example on teleport. - bool had_capability = LLAvatarNameCache::hasNameLookupURL(); + LLAvatarNameCache *name_cache = LLAvatarNameCache::getInstance(); + bool had_capability = LLAvatarNameCache::getInstance()->hasNameLookupURL(); std::string name_lookup_url; name_lookup_url.reserve(128); // avoid a memory allocation below name_lookup_url = region->getCapability("GetDisplayNames"); @@ -5160,12 +5161,12 @@ void LLAppViewer::idleNameCache() { name_lookup_url += '/'; } - LLAvatarNameCache::setNameLookupURL(name_lookup_url); + name_cache->setNameLookupURL(name_lookup_url); } else { // Display names not available on this region - LLAvatarNameCache::setNameLookupURL( std::string() ); + name_cache->setNameLookupURL( std::string() ); } // Error recovery - did we change state? @@ -5175,7 +5176,7 @@ void LLAppViewer::idleNameCache() LLVOAvatar::invalidateNameTags(); } - LLAvatarNameCache::idle(); + name_cache->idle(); } // diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 513f25e301..b0715a3afd 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -154,7 +154,7 @@ LLAvatarList::LLAvatarList(const Params& p) mLITUpdateTimer->start(); } - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLAvatarList::handleDisplayNamesOptionChanged, this)); + LLAvatarNameCache::getInstance()->addUseDisplayNamesCallback(boost::bind(&LLAvatarList::handleDisplayNamesOptionChanged, this)); } diff --git a/indra/newview/llfloaterconversationpreview.cpp b/indra/newview/llfloaterconversationpreview.cpp index 66198b3bf6..4905ce5fc2 100644 --- a/indra/newview/llfloaterconversationpreview.cpp +++ b/indra/newview/llfloaterconversationpreview.cpp @@ -221,7 +221,7 @@ void LLFloaterConversationPreview::showHistory() else { std::string legacy_name = gCacheName->buildLegacyName(from); - from_id = LLAvatarNameCache::findIdByName(legacy_name); + from_id = LLAvatarNameCache::getInstance()->findIdByName(legacy_name); } LLChat chat; diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index 30d05ae287..21420b122b 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -237,7 +237,7 @@ BOOL LLFloaterIMContainer::postBuild() collapseMessagesPane(gSavedPerAccountSettings.getBOOL("ConversationsMessagePaneCollapsed")); collapseConversationsPane(gSavedPerAccountSettings.getBOOL("ConversationsListPaneCollapsed"), false); - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); + LLAvatarNameCache::getInstance()->addUseDisplayNamesCallback(boost::bind(&LLFloaterIMSessionTab::processChatHistoryStyleUpdate, false)); mMicroChangedSignal = LLVoiceClient::getInstance()->MicroChangedCallback(boost::bind(&LLFloaterIMContainer::updateSpeakBtnState, this)); if (! mMessagesPane->isCollapsed() && ! mConversationsPane->isCollapsed()) @@ -267,7 +267,7 @@ BOOL LLFloaterIMContainer::postBuild() // We'll take care of view updates on idle gIdleCallbacks.addFunction(idle, this); // When display name option change, we need to reload all participant names - LLAvatarNameCache::addUseDisplayNamesCallback(boost::bind(&LLFloaterIMContainer::processParticipantsStyleUpdate, this)); + LLAvatarNameCache::getInstance()->addUseDisplayNamesCallback(boost::bind(&LLFloaterIMContainer::processParticipantsStyleUpdate, this)); mParticipantRefreshTimer.setTimerExpirySec(0); mParticipantRefreshTimer.start(); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index f9efd13608..a6531ed7e1 100644 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -228,7 +228,7 @@ void LLFloaterIMNearbyChat::loadHistory() else { std::string legacy_name = gCacheName->buildLegacyName(from); - from_id = LLAvatarNameCache::findIdByName(legacy_name); + from_id = LLAvatarNameCache::getInstance()->findIdByName(legacy_name); } LLChat chat; diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index 98e4cefebb..64a71c502d 100644 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -278,13 +278,13 @@ bool callback_clear_browser_cache(const LLSD& notification, const LLSD& response void handleNameTagOptionChanged(const LLSD& newvalue) { - LLAvatarNameCache::setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); + LLAvatarNameCache::getInstance()->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); LLVOAvatar::invalidateNameTags(); } void handleDisplayNamesOptionChanged(const LLSD& newvalue) { - LLAvatarNameCache::setUseDisplayNames(newvalue.asBoolean()); + LLAvatarNameCache::getInstance()->setUseDisplayNames(newvalue.asBoolean()); LLVOAvatar::invalidateNameTags(); } diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index d59c301210..3606a439a6 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -695,7 +695,7 @@ void LLIMProcessing::processNewMessage(LLUUID from_id, // The group notice packet does not have an AgentID. Obtain one from the name cache. // If last name is "Resident" strip it out so the cache name lookup works. std::string legacy_name = gCacheName->buildLegacyName(original_name); - agent_id = LLAvatarNameCache::findIdByName(legacy_name); + agent_id = LLAvatarNameCache::getInstance()->findIdByName(legacy_name); if (agent_id.isNull()) { diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 8ec8c0a563..fc2f50b3f6 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -806,7 +806,7 @@ void LLIMModel::LLIMSession::addMessagesFromHistory(const std::list<LLSD>& histo { // convert it to a legacy name if we have a complete name std::string legacy_name = gCacheName->buildLegacyName(from); - from_id = LLAvatarNameCache::findIdByName(legacy_name); + from_id = LLAvatarNameCache::getInstance()->findIdByName(legacy_name); } std::string timestamp = msg[LL_IM_TIME]; diff --git a/indra/newview/llnotificationhandlerutil.cpp b/indra/newview/llnotificationhandlerutil.cpp index 6a58196760..9a3f1a853a 100644 --- a/indra/newview/llnotificationhandlerutil.cpp +++ b/indra/newview/llnotificationhandlerutil.cpp @@ -177,7 +177,7 @@ void LLHandlerUtil::logGroupNoticeToIMGroup( { // Legacy support and fallback method // if we can't retrieve sender id from group notice system message, try to lookup it from cache - sender_id = LLAvatarNameCache::findIdByName(sender_name); + sender_id = LLAvatarNameCache::getInstance()->findIdByName(sender_name); } logToIM(IM_SESSION_GROUP_START, group_name, sender_name, payload["message"], diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 8be453ad6c..15b3ba75c9 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2833,9 +2833,10 @@ void LLStartUp::initNameCache() // Start cache in not-running state until we figure out if we have // capabilities for display name lookup - LLAvatarNameCache::initClass(false,gSavedSettings.getBOOL("UsePeopleAPI")); - LLAvatarNameCache::setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); - LLAvatarNameCache::setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); + LLAvatarNameCache* cache_inst = LLAvatarNameCache::getInstance(); + cache_inst->setUsePeopleAPI(gSavedSettings.getBOOL("UsePeopleAPI")); + cache_inst->setUseDisplayNames(gSavedSettings.getBOOL("UseDisplayNames")); + cache_inst->setUseUsernames(gSavedSettings.getBOOL("NameTagShowUsernames")); } @@ -2850,8 +2851,6 @@ void LLStartUp::initExperiences() void LLStartUp::cleanupNameCache() { - SUBSYSTEM_CLEANUP(LLAvatarNameCache); - delete gCacheName; gCacheName = NULL; } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 8f90225359..f1c073ed84 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -8653,7 +8653,6 @@ class LLWorldPostProcess : public view_listener_t void handle_flush_name_caches() { - SUBSYSTEM_CLEANUP(LLAvatarNameCache); if (gCacheName) gCacheName->clear(); } |