DRTVWR-493 LLAvatarNameCache to singletone
parent
2752e342f6
commit
779b5627c5
|
|
@ -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;
|
||||
// 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;
|
||||
|
||||
// Accumulated agent IDs for next query against service
|
||||
typedef std::set<LLUUID> ask_queue_t;
|
||||
ask_queue_t sAskQueue;
|
||||
// Send bulk lookup requests a few times a second at most.
|
||||
// Only need per-frame timing resolution.
|
||||
static LLFrameTimer sRequestTimer;
|
||||
|
||||
// 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();
|
||||
|
||||
bool expirationFromCacheControl(const LLSD& headers, F64 *expires);
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
//static, wrapper
|
||||
bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
|
||||
{
|
||||
if (sRunning)
|
||||
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::getName(const LLUUID& agent_id, LLAvatarName *av_name)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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"],
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8653,7 +8653,6 @@ class LLWorldPostProcess : public view_listener_t
|
|||
|
||||
void handle_flush_name_caches()
|
||||
{
|
||||
SUBSYSTEM_CLEANUP(LLAvatarNameCache);
|
||||
if (gCacheName) gCacheName->clear();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue