diff options
Diffstat (limited to 'indra')
21 files changed, 411 insertions, 410 deletions
| diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 9739f7c607..12fc1bbcfc 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -40,6 +40,7 @@ set(llmessage_SOURCE_FILES      llchainio.cpp      llcircuit.cpp      llclassifiedflags.cpp +    llcoproceduremanager.cpp      llcorehttputil.cpp      llcurl.cpp      lldatapacker.cpp @@ -128,6 +129,7 @@ set(llmessage_HEADER_FILES      llcipher.h      llcircuit.h      llclassifiedflags.h +    llcoproceduremanager.h      llcorehttputil.h      llcurl.h      lldatapacker.h diff --git a/indra/newview/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp index db01c13079..062f2e6e42 100644 --- a/indra/newview/llcoproceduremanager.cpp +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -25,11 +25,7 @@  * $/LicenseInfo$  */ -#include "llviewerprecompiledheaders.h"  #include "linden_common.h"  - -#include "llviewercontrol.h" -  #include "llcoproceduremanager.h"  //========================================================================= @@ -141,9 +137,13 @@ LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::  {      // Attempt to look up a pool size in the configuration.  If found use that      std::string keyName = "PoolSize" + poolName; -    int size = 5; +    int size = 0; + +    if (mPropertyQueryFn && !mPropertyQueryFn.empty()) +    { +        size = mPropertyQueryFn(keyName); +    } -    size = gSavedSettings.getU32(keyName);      if (size == 0)      {   // if not found grab the know default... if there is no known           // default use a reasonable number like 5. @@ -152,7 +152,9 @@ LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::              size = DEFAULT_POOL_SIZE;          else              size = (*it).second; -        gSavedSettings.declareU32(keyName, size, "Coroutine Pool size for " + poolName, LLControlVariable::PERSIST_ALWAYS); + +        if (mPropertyDefineFn && !mPropertyDefineFn.empty()) +            mPropertyDefineFn(keyName, size, "Coroutine Pool size for " + poolName);          LL_WARNS() << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL;      } @@ -207,6 +209,12 @@ void LLCoprocedureManager::shutdown(bool hardShutdown)      mPoolMap.clear();  } +void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn) +{ +    mPropertyQueryFn = queryfn; +    mPropertyDefineFn = updatefn; +} +  //-------------------------------------------------------------------------  size_t LLCoprocedureManager::countPending() const  { diff --git a/indra/newview/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h index d7f74af76b..497367b80c 100644 --- a/indra/newview/llcoproceduremanager.h +++ b/indra/llmessage/llcoproceduremanager.h @@ -37,7 +37,12 @@ class LLCoprocedurePool;  class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager >  { +    friend class LLSingleton < LLCoprocedureManager > ; +  public: +    typedef boost::function<U32(const std::string &)> SettingQuery_t; +    typedef boost::function<void(const std::string &, U32, const std::string &)> SettingUpdate_t; +      typedef boost::function<void(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, const LLUUID &id)> CoProcedure_t;      LLCoprocedureManager(); @@ -60,6 +65,8 @@ public:      /// an immediate kill on the upload coroutine.      void shutdown(bool hardShutdown = false); +    void setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn); +      /// Returns the number of coprocedures in the queue awaiting processing.      ///      size_t countPending() const; @@ -76,12 +83,16 @@ public:      size_t count(const std::string &pool) const;  private: +      typedef boost::shared_ptr<LLCoprocedurePool> poolPtr_t;      typedef std::map<std::string, poolPtr_t> poolMap_t;      poolMap_t mPoolMap;      poolPtr_t initializePool(const std::string &poolName); + +    SettingQuery_t mPropertyQueryFn; +    SettingUpdate_t mPropertyDefineFn;  };  #endif diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index 34c4210359..36a4fc8823 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -26,53 +26,51 @@  #include "llexperiencecache.h"  #include "llavatarname.h" -#include "llframetimer.h"  #include "llhttpclient.h"  #include "llsdserialize.h" +#include "llcoros.h" +#include "lleventcoro.h" +#include "lleventfilter.h" +#include "llcoproceduremanager.h" +#include "lldir.h"  #include <set>  #include <map> -#include "boost/tokenizer.hpp" +#include <boost/tokenizer.hpp>  #include <boost/concept_check.hpp> - -typedef std::map<LLUUID, LLUUID> KeyMap; -KeyMap privateToPublicKeyMap; - - -std::string sLookupURL; - -typedef std::map<LLUUID, F64> pending_queue_t; -pending_queue_t sPendingQueue; - -int sMaximumLookups = 10; - -LLFrameTimer sRequestTimer; - -// Periodically clean out expired entries from the cache -LLFrameTimer sEraseExpiredTimer; - -  //=========================================================================  namespace LLExperienceCacheImpl  { -	bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age);  	void mapKeys(const LLSD& legacyKeys); +    F64 getErrorRetryDeltaTime(S32 status, LLSD headers); +    bool maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age); + +    static const std::string PRIVATE_KEY    = "private_id"; +    static const std::string EXPERIENCE_ID  = "public_id"; + +    static const std::string MAX_AGE("max-age"); +    static const boost::char_separator<char> EQUALS_SEPARATOR("="); +    static const boost::char_separator<char> COMMA_SEPARATOR(","); + +    // *TODO$: this seems to be tied to mapKeys which is used by bootstrap.... but I don't think that bootstrap is used. +    typedef std::map<LLUUID, LLUUID> KeyMap; +    KeyMap privateToPublicKeyMap;  }  //=========================================================================  const std::string LLExperienceCache::PRIVATE_KEY	= "private_id";  const std::string LLExperienceCache::MISSING       	= "DoesNotExist"; -const std::string LLExperienceCache::AGENT_ID      	= "agent_id"; -const std::string LLExperienceCache::GROUP_ID      	= "group_id"; +const std::string LLExperienceCache::AGENT_ID      = "agent_id"; +const std::string LLExperienceCache::GROUP_ID      = "group_id";  const std::string LLExperienceCache::EXPERIENCE_ID	= "public_id";  const std::string LLExperienceCache::NAME			= "name";  const std::string LLExperienceCache::PROPERTIES		= "properties";  const std::string LLExperienceCache::EXPIRES		= "expiration";    const std::string LLExperienceCache::DESCRIPTION	= "description";  const std::string LLExperienceCache::QUOTA         	= "quota"; -const std::string LLExperienceCache::MATURITY      	= "maturity"; -const std::string LLExperienceCache::METADATA      	= "extended_metadata"; +const std::string LLExperienceCache::MATURITY      = "maturity"; +const std::string LLExperienceCache::METADATA      = "extended_metadata";  const std::string LLExperienceCache::SLURL         	= "slurl";  // should be in sync with experience-api/experiences/models.py @@ -80,20 +78,51 @@ const int LLExperienceCache::PROPERTY_INVALID		= 1 << 0;  const int LLExperienceCache::PROPERTY_PRIVILEGED	= 1 << 3;  const int LLExperienceCache::PROPERTY_GRID			= 1 << 4;  const int LLExperienceCache::PROPERTY_PRIVATE		= 1 << 5; -const int LLExperienceCache::PROPERTY_DISABLED		= 1 << 6;   -const int LLExperienceCache::PROPERTY_SUSPENDED		= 1 << 7; +const int LLExperienceCache::PROPERTY_DISABLED	= 1 << 6;   +const int LLExperienceCache::PROPERTY_SUSPENDED	= 1 << 7;  // default values -const F64 LLExperienceCache::DEFAULT_EXPIRATION		= 600.0; +const F64 LLExperienceCache::DEFAULT_EXPIRATION	= 600.0;  const S32 LLExperienceCache::DEFAULT_QUOTA			= 128; // this is megabytes  //========================================================================= -LLExperienceCache::LLExperienceCache() +LLExperienceCache::LLExperienceCache(): +    mShutdown(false)  {  }  LLExperienceCache::~LLExperienceCache()  { + +} + +void LLExperienceCache::initSingleton() +{ +    mCacheFileName = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); + +    LL_INFOS("ExperienceCache") << "Loading " << mCacheFileName << LL_ENDL; +    llifstream cache_stream(mCacheFileName.c_str()); + +    if (cache_stream.is_open()) +    { +        cache_stream >> (*this); +    } + +    LLCoros::instance().launch("LLExperienceCache::idleCoro", +        boost::bind(&LLExperienceCache::idleCoro, this)); + +} + +void LLExperienceCache::cleanup() +{ +    LL_INFOS("ExperienceCache") << "Saving " << mCacheFileName << LL_ENDL; + +    llofstream cache_stream(mCacheFileName.c_str()); +    if (cache_stream.is_open()) +    { +        cache_stream << (*this); +    } +    mShutdown = true;  }  //------------------------------------------------------------------------- @@ -110,18 +139,18 @@ void LLExperienceCache::importFile(std::istream& istr)      for (; it != experiences.endMap(); ++it)      {          public_key.set(it->first); -        sCache[public_key] = it->second; +        mCache[public_key] = it->second;      } -    LL_DEBUGS("ExperienceCache") << "importFile() loaded " << sCache.size() << LL_ENDL; +    LL_DEBUGS("ExperienceCache") << "importFile() loaded " << mCache.size() << LL_ENDL;  }  void LLExperienceCache::exportFile(std::ostream& ostr) const  {      LLSD experiences; -    cache_t::const_iterator it = sCache.begin(); -    for (; it != sCache.end(); ++it) +    cache_t::const_iterator it = mCache.begin(); +    for (; it != mCache.end(); ++it)      {          if (!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() ||              it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID)) @@ -136,7 +165,7 @@ void LLExperienceCache::exportFile(std::ostream& ostr) const      LLSDSerialize::toPrettyXML(data, ostr);  } -// *TODO$: Rider: These three functions not seem to be used... it may be useful in testing. +// *TODO$: Rider: This method does not seem to be used... it may be useful in testing.  void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration)  {  	LLExperienceCacheImpl::mapKeys(legacyKeys); @@ -166,8 +195,8 @@ LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_i      if (private_key.isNull())          return LLUUID::null; -    KeyMap::const_iterator it = privateToPublicKeyMap.find(private_key); -    if (it == privateToPublicKeyMap.end()) +    LLExperienceCacheImpl::KeyMap::const_iterator it = LLExperienceCacheImpl::privateToPublicKeyMap.find(private_key); +    if (it == LLExperienceCacheImpl::privateToPublicKeyMap.end())      {          if (null_if_not_found)          { @@ -182,8 +211,10 @@ LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_i  //=========================================================================  void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& experience)  { -	sCache[public_key]=experience; -	LLSD & row = sCache[public_key]; +    LL_INFOS("ExperienceCache") << "Processing experience \"" << experience[NAME] << "\" with key " << public_key.asString() << LL_ENDL; + +	mCache[public_key]=experience; +	LLSD & row = mCache[public_key];  	if(row.has(EXPIRES))  	{ @@ -192,233 +223,148 @@ void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD&  	if(row.has(EXPERIENCE_ID))  	{ -		sPendingQueue.erase(row[EXPERIENCE_ID].asUUID()); +		mPendingQueue.erase(row[EXPERIENCE_ID].asUUID());  	}  	//signal -	signal_map_t::iterator sig_it =	sSignalMap.find(public_key); -	if (sig_it != sSignalMap.end()) +	signal_map_t::iterator sig_it =	mSignalMap.find(public_key); +	if (sig_it != mSignalMap.end())  	{  		signal_ptr signal = sig_it->second;  		(*signal)(experience); -		sSignalMap.erase(public_key); +		mSignalMap.erase(public_key);  	}  }  const LLExperienceCache::cache_t& LLExperienceCache::getCached()  { -	return sCache; -} - -void LLExperienceCache::setMaximumLookups(int maximumLookups) -{ -	sMaximumLookups = maximumLookups; +	return mCache;  } - -bool LLExperienceCache::expirationFromCacheControl(LLSD headers, F64 *expires) +void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, std::string url, RequestQueue_t requests)  { -	// Allow the header to override the default -	LLSD cache_control_header = headers["cache-control"]; -	if (cache_control_header.isDefined()) -	{ -		S32 max_age = 0; -		std::string cache_control = cache_control_header.asString(); -		if (max_age_from_cache_control(cache_control, &max_age)) -		{ -			LL_WARNS("ExperienceCache")  -				<< "got EXPIRES from headers, max_age " << max_age  -				<< LL_ENDL; -			F64 now = LLFrameTimer::getTotalSeconds(); -			*expires = now + (F64)max_age; -			return true; -		} -	} -	return false; -} +    LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); +    //LL_INFOS("requestExperiencesCoro") << "url: " << url << LL_ENDL; -static const std::string MAX_AGE("max-age"); -static const boost::char_separator<char> EQUALS_SEPARATOR("="); -static const boost::char_separator<char> COMMA_SEPARATOR(","); +    LLSD result = httpAdapter->getAndYield(httpRequest, url); +         +    LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; +    LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); +    if (!status) +    { +        F64 now = LLFrameTimer::getTotalSeconds(); -class LLExperienceResponder : public LLHTTPClient::Responder -{ -public: -	LLExperienceResponder(const ask_queue_t& keys) -		:mKeys(keys) -	{ - -	} - -	/*virtual*/ void httpCompleted() -	{ -		LLSD experiences = getContent()["experience_keys"]; -		LLSD::array_const_iterator it = experiences.beginArray(); -		for( /**/ ; it != experiences.endArray(); ++it) -		{ -			const LLSD& row = *it; -			LLUUID public_key = row[EXPERIENCE_ID].asUUID(); - - -			LL_DEBUGS("ExperienceCache") << "Received result for " << public_key  -				<< " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL ; - -			processExperience(public_key, row); -		} - -		LLSD error_ids = getContent()["error_ids"]; -		LLSD::array_const_iterator errIt = error_ids.beginArray(); -		for( /**/ ; errIt != error_ids.endArray() ; ++errIt ) -		{ -			LLUUID id = errIt->asUUID();		 -			LLSD exp; -			exp[EXPIRES]=DEFAULT_EXPIRATION; -			exp[EXPERIENCE_ID] = id; -			exp[PROPERTIES]=PROPERTY_INVALID; -			exp[MISSING]=true; -            exp[QUOTA] = DEFAULT_QUOTA; - -			processExperience(id, exp); -			LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL ; -		} - -		LL_DEBUGS("ExperienceCache") << sCache.size() << " cached experiences" << LL_ENDL; -	} - -	/*virtual*/ void httpFailure() -	{ - 		LL_WARNS("ExperienceCache") << "Request failed "<<getStatus()<<" "<<getReason()<< LL_ENDL; - 		// We're going to construct a dummy record and cache it for a while, - 		// either briefly for a 503 Service Unavailable, or longer for other - 		// errors. - 		F64 retry_timestamp = errorRetryTimestamp(getStatus()); -  -  - 		// Add dummy records for all agent IDs in this request - 		ask_queue_t::const_iterator it = mKeys.begin(); - 		for ( ; it != mKeys.end(); ++it) -		{ - -			LLSD exp = get(it->first); +        LLSD headers = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; +        // build dummy entries for the failed requests +        for (RequestQueue_t::const_iterator it = requests.begin(); it != requests.end(); ++it) +        { +            LLSD exp = get(*it);              //leave the properties alone if we already have a cache entry for this xp -            if(exp.isUndefined()) +            if (exp.isUndefined())              { -                exp[PROPERTIES]=PROPERTY_INVALID; +                exp[PROPERTIES] = PROPERTY_INVALID;              } -			exp[EXPIRES]=retry_timestamp; -			exp[EXPERIENCE_ID] = it->first; -			exp["key_type"] = it->second; -			exp["uuid"] = it->first; -			exp["error"] = (LLSD::Integer)getStatus(); +            exp[EXPIRES] = now + LLExperienceCacheImpl::getErrorRetryDeltaTime(status, headers); +            exp[EXPERIENCE_ID] = *it; +            exp["key_type"] = EXPERIENCE_ID; +            exp["uuid"] = *it; +            exp["error"] = (LLSD::Integer)status.getType();              exp[QUOTA] = DEFAULT_QUOTA; - 			LLExperienceCache::processExperience(it->first, exp); - 		} - -	} - -	// Return time to retry a request that generated an error, based on -	// error type and headers.  Return value is seconds-since-epoch. -	F64 errorRetryTimestamp(S32 status) -	{ +            processExperience(*it, exp); +        } +        return; +    } -		// Retry-After takes priority -		LLSD retry_after = getResponseHeaders()["retry-after"]; -		if (retry_after.isDefined()) -		{ -			// We only support the delta-seconds type -			S32 delta_seconds = retry_after.asInteger(); -			if (delta_seconds > 0) -			{ -				// ...valid delta-seconds -				return F64(delta_seconds); -			} -		} +    LLSD experiences = result["experience_keys"]; +     +    for (LLSD::array_const_iterator it = experiences.beginArray();  +        it != experiences.endArray(); ++it) +    { +        const LLSD& row = *it; +        LLUUID public_key = row[EXPERIENCE_ID].asUUID(); -		// If no Retry-After, look for Cache-Control max-age -		F64 expires = 0.0; -		if (LLExperienceCache::expirationFromCacheControl(getResponseHeaders(), &expires)) -		{ -			return expires; -		} +        LL_DEBUGS("ExperienceCache") << "Received result for " << public_key +            << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL; -		// No information in header, make a guess -		if (status == 503) -		{ -			// ...service unavailable, retry soon -			const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min -			return SERVICE_UNAVAILABLE_DELAY; -		} -		else if (status == 499) -		{ -			// ...we were probably too busy, retry quickly -			const F64 BUSY_DELAY = 10.0; // 10 seconds -			return BUSY_DELAY; +        processExperience(public_key, row); +    } -		} -		else -		{ -			// ...other unexpected error -			const F64 DEFAULT_DELAY = 3600.0; // 1 hour -			return DEFAULT_DELAY; -		} -	} +    LLSD error_ids = result["error_ids"]; +     +    for (LLSD::array_const_iterator errIt = error_ids.beginArray();  +        errIt != error_ids.endArray(); ++errIt) +    { +        LLUUID id = errIt->asUUID(); +        LLSD exp; +        exp[EXPIRES] = DEFAULT_EXPIRATION; +        exp[EXPERIENCE_ID] = id; +        exp[PROPERTIES] = PROPERTY_INVALID; +        exp[MISSING] = true; +        exp[QUOTA] = DEFAULT_QUOTA; + +        processExperience(id, exp); +        LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL; +    } -private: -	ask_queue_t mKeys; -}; +}  void LLExperienceCache::requestExperiences()  { -	if(sAskQueue.empty() || sLookupURL.empty()) -		return; - -	F64 now = LLFrameTimer::getTotalSeconds(); +    if (mCapability.empty()) +    { +        LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; +        return; +    } -	const U32 EXP_URL_SEND_THRESHOLD = 3000; -	const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD/UUID_STR_LENGTH; +    std::string urlBase = mCapability("GetExperienceInfo"); +    if (urlBase.empty()) +    { +        LL_WARNS("ExperienceCache") << "No Experience capability." << LL_ENDL; +        return; +    } -	std::ostringstream ostr; +    if (*urlBase.rbegin() != '/') +    { +        urlBase += "/"; +    } +    urlBase += "id/"; -	ask_queue_t keys; -	ostr << sLookupURL << "?page_size=" << PAGE_SIZE; +	F64 now = LLFrameTimer::getTotalSeconds(); -	int request_count = 0; -	while(!sAskQueue.empty() && request_count < sMaximumLookups) -	{ -		ask_queue_t::iterator it = sAskQueue.begin(); -		const LLUUID& key = it->first; -		const std::string& key_type = it->second; +    const U32 EXP_URL_SEND_THRESHOLD = 3000; +    const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD / UUID_STR_LENGTH; -		ostr << '&' << key_type << '=' << key.asString() ; -		 -		keys[key]=key_type; -		request_count++; +    std::ostringstream ostr; +    ostr << urlBase << "?page_size=" << PAGE_SIZE; +    RequestQueue_t  requests; -		sPendingQueue[key] = now; -			 -		if(ostr.tellp() > EXP_URL_SEND_THRESHOLD) -		{ -			LL_DEBUGS("ExperienceCache") <<  "requestExperiences() query: " << ostr.str() << LL_ENDL; -			LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); -			ostr.clear(); -			ostr.str(sLookupURL); -			ostr << "?page_size=" << PAGE_SIZE; -			keys.clear(); -		} -		sAskQueue.erase(it); -	} +    while (!mRequestQueue.empty()) +    { +        RequestQueue_t::iterator it = mRequestQueue.begin(); +        LLUUID key = (*it); +        mRequestQueue.erase(it); +        requests.insert(key); + +        ostr << "&" << EXPERIENCE_ID << "=" << key.asString(); +        mPendingQueue[key] = now; +         +        if (mRequestQueue.empty() || (ostr.tellp() > EXP_URL_SEND_THRESHOLD)) +        {   // request is placed in the coprocedure pool for the ExpCache cache.  Throttling is done by the pool itself. +            LLCoprocedureManager::getInstance()->enqueueCoprocedure("ExpCache", "Request", +                boost::bind(&LLExperienceCache::requestExperiencesCoro, this, _1, ostr.str(), requests) ); + +            ostr.str(std::string()); +            ostr << urlBase << "?page_size=" << PAGE_SIZE; +            requests.clear(); +        } +    } -	if(ostr.tellp() > sLookupURL.size()) -	{ -		LL_DEBUGS("ExperienceCache") <<  "requestExperiences() query 2: " << ostr.str() << LL_ENDL; -		LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); -	}  } @@ -427,9 +373,9 @@ bool LLExperienceCache::isRequestPending(const LLUUID& public_key)  	bool isPending = false;  	const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0; -	pending_queue_t::const_iterator it = sPendingQueue.find(public_key); +    PendingQueue_t::const_iterator it = mPendingQueue.find(public_key); -	if(it != sPendingQueue.end()) +	if(it != mPendingQueue.end())  	{  		F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS;  		isPending = (it->second > expire_time); @@ -438,69 +384,70 @@ bool LLExperienceCache::isRequestPending(const LLUUID& public_key)  	return isPending;  } - -void LLExperienceCache::setLookupURL(const std::string& lookup_url) +void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t queryfn)  { -	sLookupURL = lookup_url; -	if(!sLookupURL.empty()) -	{ -		sLookupURL += "id/"; -	} +    mCapability = queryfn;  } -bool LLExperienceCache::hasLookupURL() -{ -	return !sLookupURL.empty(); -} -void LLExperienceCache::idle() +void LLExperienceCache::idleCoro()  { -	const F32 SECS_BETWEEN_REQUESTS = 0.1f; -	if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS)) -	{ -		return; -	} +    const F32 SECS_BETWEEN_REQUESTS = 0.5f; +    const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds -	// Must be large relative to above -	const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds -	if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) -	{ -		eraseExpired(); -	} +    LL_INFOS("ExperienceCache") << "Launching Experience cache idle coro." << LL_ENDL; +    LLEventTimeout timeout; -	if(!sAskQueue.empty()) -	{ -		requestExperiences(); -	} +    do  +    { +        timeout.eventAfter(SECS_BETWEEN_REQUESTS, LLSD()); +        llcoro::waitForEventOn(timeout); + +        if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) +        { +            eraseExpired(); +        } + +        if (!mRequestQueue.empty()) +        { +            requestExperiences(); +        } + +    } while (!mShutdown); + +    // The coroutine system will likely be shut down by the time we get to this point +    // (or at least no further cycling will occur on it since the user has decided to quit.)  }  void LLExperienceCache::erase(const LLUUID& key)  { -	cache_t::iterator it = sCache.find(key); +	cache_t::iterator it = mCache.find(key); -	if(it != sCache.end()) +	if(it != mCache.end())  	{ -		sCache.erase(it); +		mCache.erase(it);  	}  }  void LLExperienceCache::eraseExpired()  {  	F64 now = LLFrameTimer::getTotalSeconds(); -	cache_t::iterator it = sCache.begin(); -	while (it != sCache.end()) +	cache_t::iterator it = mCache.begin(); +	while (it != mCache.end())  	{  		cache_t::iterator cur = it;  		LLSD& exp = cur->second;  		++it; +        //LL_INFOS("ExperienceCache") << "Testing experience \"" << exp[NAME] << "\" with exp time " << exp[EXPIRES].asReal() << "(now = " << now << ")" << LL_ENDL; +  		if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now)  		{              if(!exp.has(EXPERIENCE_ID))  			{                  LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ; -                sCache.erase(cur); -				} +                mCache.erase(cur); +			}              else              {                  LLUUID id = exp[EXPERIENCE_ID].asUUID(); @@ -512,7 +459,7 @@ void LLExperienceCache::eraseExpired()  				else  				{                      LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ; -					sCache.erase(cur); +					mCache.erase(cur);  				}  			}  		} @@ -521,11 +468,11 @@ void LLExperienceCache::eraseExpired()  bool LLExperienceCache::fetch(const LLUUID& key, bool refresh/* = true*/)  { -	if(!key.isNull() && !isRequestPending(key) && (refresh || sCache.find(key)==sCache.end())) +	if(!key.isNull() && !isRequestPending(key) && (refresh || mCache.find(key)==mCache.end()))  	{ -		LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL ; -		sAskQueue[key]=EXPERIENCE_ID; +		LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL; +        mRequestQueue.insert(key);  		return true;  	}  	return false; @@ -549,13 +496,12 @@ const LLSD& LLExperienceCache::get(const LLUUID& key)  	if(key.isNull())   		return empty; -	cache_t::const_iterator it = sCache.find(key); +	cache_t::const_iterator it = mCache.find(key); -	if (it != sCache.end()) +	if (it != mCache.end())  	{  		return it->second;  	} -  	fetch(key);  	return empty; @@ -565,8 +511,8 @@ void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::Callback_t slo  	if(key.isNull())   		return; -	cache_t::const_iterator it = sCache.find(key); -	if (it != sCache.end()) +	cache_t::const_iterator it = mCache.find(key); +	if (it != mCache.end())  	{  		// ...name already exists in cache, fire callback now  		callback_signal_t signal; @@ -580,28 +526,10 @@ void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::Callback_t slo  	signal_ptr signal = signal_ptr(new callback_signal_t()); -	std::pair<signal_map_t::iterator, bool> result = sSignalMap.insert(signal_map_t::value_type(key, signal)); +	std::pair<signal_map_t::iterator, bool> result = mSignalMap.insert(signal_map_t::value_type(key, signal));  	if (!result.second) -		signal = result.first.second; +		signal = (*result.first).second;  	signal->connect(slot); -	 -#if 0 -	// always store additional callback, even if request is pending -	signal_map_t::iterator sig_it = sSignalMap.find(key); -	if (sig_it == sSignalMap.end()) -	{ -		// ...new callback for this id -		signal_ptr signal = signal_ptr(new callback_signal_t()); -		signal->connect(slot); -		sSignalMap[key] = signal; -	} -	else -	{ -		// ...existing callback, bind additional slot -		callback_signal_t* signal = sig_it->second; -		signal->connect(slot); -	} -#endif  }  //========================================================================= @@ -610,14 +538,71 @@ void LLExperienceCacheImpl::mapKeys(const LLSD& legacyKeys)  	LLSD::array_const_iterator exp = legacyKeys.beginArray();  	for (/**/; exp != legacyKeys.endArray(); ++exp)  	{ -		if (exp->has(LLExperienceCache::EXPERIENCE_ID) && exp->has(LLExperienceCache::PRIVATE_KEY)) +        if (exp->has(LLExperienceCacheImpl::EXPERIENCE_ID) && exp->has(LLExperienceCacheImpl::PRIVATE_KEY))  		{ -			privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()] = (*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID(); +            LLExperienceCacheImpl::privateToPublicKeyMap[(*exp)[LLExperienceCacheImpl::PRIVATE_KEY].asUUID()] =  +                (*exp)[LLExperienceCacheImpl::EXPERIENCE_ID].asUUID();  		}  	}  } -bool LLExperienceCacheImpl::max_age_from_cache_control(const std::string& cache_control, S32 *max_age) +// Return time to retry a request that generated an error, based on +// error type and headers.  Return value is seconds-since-epoch. +F64 LLExperienceCacheImpl::getErrorRetryDeltaTime(S32 status, LLSD headers) +{ + +    // Retry-After takes priority +    LLSD retry_after = headers["retry-after"]; +    if (retry_after.isDefined()) +    { +        // We only support the delta-seconds type +        S32 delta_seconds = retry_after.asInteger(); +        if (delta_seconds > 0) +        { +            // ...valid delta-seconds +            return F64(delta_seconds); +        } +    } + +    // If no Retry-After, look for Cache-Control max-age +    // Allow the header to override the default +    LLSD cache_control_header = headers["cache-control"]; +    if (cache_control_header.isDefined()) +    { +        S32 max_age = 0; +        std::string cache_control = cache_control_header.asString(); +        if (LLExperienceCacheImpl::maxAgeFromCacheControl(cache_control, &max_age)) +        { +            LL_WARNS("ExperienceCache") +                << "got EXPIRES from headers, max_age " << max_age +                << LL_ENDL; +            return (F64)max_age; +        } +    } + +    // No information in header, make a guess +    if (status == 503) +    { +        // ...service unavailable, retry soon +        const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min +        return SERVICE_UNAVAILABLE_DELAY; +    } +    else if (status == 499) +    { +        // ...we were probably too busy, retry quickly +        const F64 BUSY_DELAY = 10.0; // 10 seconds +        return BUSY_DELAY; + +    } +    else +    { +        // ...other unexpected error +        const F64 DEFAULT_DELAY = 3600.0; // 1 hour +        return DEFAULT_DELAY; +    } +} + +bool LLExperienceCacheImpl::maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age)  {  	// Split the string on "," to get a list of directives  	typedef boost::tokenizer<boost::char_separator<char> > tokenizer; diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index 8da038a8c3..937225a80a 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -31,7 +31,9 @@  #include "linden_common.h"  #include "llsingleton.h" +#include "llframetimer.h"  #include "llsd.h" +#include "llcorehttputil.h"  #include <boost/signals2.hpp>  #include <boost/function.hpp> @@ -44,8 +46,11 @@ class LLExperienceCache: public LLSingleton < LLExperienceCache >      friend class LLSingleton < LLExperienceCache > ;  public: +    typedef boost::function<std::string(const std::string &)> CapabilityQuery_t;      typedef boost::function<void(const LLSD &)> Callback_t; +    void cleanup(); +      void erase(const LLUUID& key);      bool fetch(const LLUUID& key, bool refresh = false);      void insert(const LLSD& experience_data); @@ -54,7 +59,39 @@ public:      // If name information is in cache, callback will be called immediately.      void get(const LLUUID& key, Callback_t slot); +    bool isRequestPending(const LLUUID& public_key); + +    void setCapabilityQuery(CapabilityQuery_t queryfn); + +    static const std::string NAME;			// "name" +    static const std::string EXPERIENCE_ID;	// "public_id" +    static const std::string AGENT_ID;      // "agent_id" +    static const std::string GROUP_ID;      // "group_id" +    static const std::string PROPERTIES;	// "properties" +    static const std::string EXPIRES;		// "expiration"   +    static const std::string DESCRIPTION;	// "description" +    static const std::string QUOTA;         // "quota" +    static const std::string MATURITY;      // "maturity" +    static const std::string METADATA;      // "extended_metadata" +    static const std::string SLURL;         // "slurl" + +    static const std::string MISSING;       // "DoesNotExist" + +    // should be in sync with experience-api/experiences/models.py +    static const int PROPERTY_INVALID;		// 1 << 0 +    static const int PROPERTY_PRIVILEGED;	// 1 << 3 +    static const int PROPERTY_GRID;			// 1 << 4 +    static const int PROPERTY_PRIVATE;		// 1 << 5 +    static const int PROPERTY_DISABLED;		// 1 << 6   +    static const int PROPERTY_SUSPENDED;	// 1 << 7 +  private: +    LLExperienceCache(); +    virtual ~LLExperienceCache(); + +    virtual void initSingleton(); + +      // Callback types for get()       typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t;  	typedef boost::shared_ptr<callback_signal_t> signal_ptr; @@ -64,63 +101,43 @@ private:  	typedef std::map<LLUUID, signal_ptr> signal_map_t;  	typedef std::map<LLUUID, LLSD> cache_t; -	typedef std::set<LLUUID> ask_queue_t; -	 -	 +	typedef std::set<LLUUID> RequestQueue_t; +    typedef std::map<LLUUID, F64> PendingQueue_t; +  	//--------------------------------------------  	static const std::string PRIVATE_KEY;	// "private_id" -	static const std::string MISSING;       // "DoesNotExist" -	 -	static const std::string AGENT_ID;      // "agent_id" -	static const std::string GROUP_ID;      // "group_id" -	static const std::string EXPERIENCE_ID;	// "public_id" -	static const std::string NAME;			// "name" -	static const std::string PROPERTIES;	// "properties" -	static const std::string EXPIRES;		// "expiration"   -	static const std::string DESCRIPTION;	// "description" -	static const std::string QUOTA;         // "quota" -	static const std::string MATURITY;      // "maturity" -	static const std::string METADATA;      // "extended_metadata" -	static const std::string SLURL;         // "slurl" -	 -	// should be in sync with experience-api/experiences/models.py -	static const int PROPERTY_INVALID;		// 1 << 0 -	static const int PROPERTY_PRIVILEGED;	// 1 << 3 -	static const int PROPERTY_GRID;			// 1 << 4 -	static const int PROPERTY_PRIVATE;		// 1 << 5 -	static const int PROPERTY_DISABLED;		// 1 << 6   -	static const int PROPERTY_SUSPENDED;	// 1 << 7  	// default values  	static const F64 DEFAULT_EXPIRATION; 	// 600.0  	static const S32 DEFAULT_QUOTA; 		// 128 this is megabytes  //-------------------------------------------- -    LLExperienceCache(); -    virtual ~LLExperienceCache(); - -    void exportFile(std::ostream& ostr) const; -    void importFile(std::istream& istr); - -//--------------------------------------------      void processExperience(const LLUUID& public_key, const LLSD& experience);  //-------------------------------------------- -	cache_t			sCache; -	signal_map_t	sSignalMap;	 -	ask_queue_t		sAskQueue; -	 +	cache_t			mCache; +	signal_map_t	mSignalMap;	 +	RequestQueue_t	mRequestQueue; +    PendingQueue_t  mPendingQueue; + +    LLFrameTimer    mRequestTimer; +    LLFrameTimer    mEraseExpiredTimer;    // Periodically clean out expired entries from the cache +    CapabilityQuery_t mCapability; +    std::string     mCacheFileName; +    bool            mShutdown; + +    void idleCoro();  	void eraseExpired(); -	 -	void setLookupURL(const std::string& lookup_url); -	bool hasLookupURL(); +    void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t); +    void requestExperiences();  	void setMaximumLookups(int maximumLookups); -	void idle(); -	void bootstrap(const LLSD& legacyKeys, int initialExpiration); -	 +    void bootstrap(const LLSD& legacyKeys, int initialExpiration); +    void exportFile(std::ostream& ostr) const; +    void importFile(std::istream& istr); +    //   	const cache_t& getCached();  	// maps an experience private key to the experience id diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 259fbde806..d192aac448 100755 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -11,11 +11,13 @@ include(LLMessage)  include(LLCoreHttp)  include(LLRender)  include(LLWindow) +include(LLCoreHttp)  include(LLVFS)  include(LLXML)  include_directories(      ${LLCOMMON_INCLUDE_DIRS} +    ${LLCOREHTTP_INCLUDE_DIRS}      ${LLIMAGE_INCLUDE_DIRS}      ${LLINVENTORY_INCLUDE_DIRS}      ${LLMATH_INCLUDE_DIRS} diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index eb7f98e618..e76f2a1550 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1430,7 +1430,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const          return LLTrans::getString("ExperienceNameNull");      } -    const LLSD& experience_details = LLExperienceCache::get(experience_id); +    const LLSD& experience_details = LLExperienceCache::getInstance()->get(experience_id);      if(!experience_details.isUndefined())      {  		std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString(); @@ -1438,7 +1438,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const      }      addObserver(experience_id_string, url, cb); -    LLExperienceCache::get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); +    LLExperienceCache::getInstance()->get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1));      return LLTrans::getString("LoadingData");  } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index fe9c7c0fc0..090879e372 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -161,7 +161,6 @@ set(viewer_SOURCE_FILES      llconversationloglistitem.cpp      llconversationmodel.cpp      llconversationview.cpp -    llcoproceduremanager.cpp      llcurrencyuimanager.cpp      llcylinder.cpp      lldateutil.cpp @@ -771,7 +770,6 @@ set(viewer_HEADER_FILES      llconversationloglistitem.h      llconversationmodel.h      llconversationview.h -    llcoproceduremanager.h      llcurrencyuimanager.h      llcylinder.h      lldateutil.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index e7dd378edd..3316f1e654 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -953,6 +953,15 @@ BOOL LLAgent::inPrelude()  } +std::string LLAgent::getRegionCapability(const std::string &name) +{ +    if (!mRegionp) +        return std::string(); +     +    return mRegionp->getCapability(name); +} + +  //-----------------------------------------------------------------------------  // canManageEstate()  //----------------------------------------------------------------------------- diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 0ba3dea427..5731f4db89 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -262,6 +262,9 @@ public:  	LLHost			getRegionHost() const;  	BOOL			inPrelude(); +    // Capability  +    std::string     getRegionCapability(const std::string &name); // short hand for if (getRegion()) { getRegion()->getCapability(name) } +  	/**  	 * Register a boost callback to be called when the agent changes regions  	 * Note that if you need to access a capability for the region, you may need to wait diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9b9b591cd1..e13a9d96c7 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -228,7 +228,7 @@  #include "llmachineid.h"  #include "llmainlooprepeater.h" - +#include "llcoproceduremanager.h"  #include "llviewereventrecorder.h" @@ -755,8 +755,11 @@ void fast_exit(int rc)  {  	_exit(rc);  } + +  } +  bool LLAppViewer::init()  {	  	setupErrorHandling(mSecondInstance); @@ -1216,6 +1219,12 @@ bool LLAppViewer::init()  	LLAgentLanguage::init(); +    /// Tell the Coprocedure manager how to discover and store the pool sizes +    // what I wanted +    LLCoprocedureManager::getInstance()->setPropertyMethods( +        boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1), +        boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); +  	return true;  } @@ -4700,31 +4709,6 @@ void LLAppViewer::saveNameCache()  } -void LLAppViewer::saveExperienceCache() -{ -	std::string filename = -		gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); -	LL_INFOS("ExperienceCache") << "Saving " << filename << LL_ENDL; -	llofstream cache_stream(filename.c_str()); -	if(cache_stream.is_open()) -	{ -		LLExperienceCache::exportFile(cache_stream); -	} -} - -void LLAppViewer::loadExperienceCache() -{ -	std::string filename = -		gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); -	LL_INFOS("ExperienceCache") << "Loading " << filename << LL_ENDL; -	llifstream cache_stream(filename.c_str()); -	if(cache_stream.is_open()) -	{ -		LLExperienceCache::importFile(cache_stream); -	} -} - -  /*!	@brief		This class is an LLFrameTimer that can be created with  				an elapsed time that starts counting up from the given value  				rather than 0.0. @@ -4920,7 +4904,6 @@ void LLAppViewer::idle()  	    // floating throughout the various object lists.  	    //  		idleNameCache(); -		idleExperienceCache();  		idleNetwork(); @@ -5350,22 +5333,6 @@ void LLAppViewer::idleNameCache()  	LLAvatarNameCache::idle();  } -void LLAppViewer::idleExperienceCache() -{ -	LLViewerRegion* region = gAgent.getRegion(); -	if (!region) return; -	 -	std::string lookup_url=region->getCapability("GetExperienceInfo");  -	if(!lookup_url.empty() && *lookup_url.rbegin() != '/') -	{ -		lookup_url += '/'; -	} -	 -	LLExperienceCache::setLookupURL(lookup_url); - -	LLExperienceCache::idle(); -} -  //  // Handle messages, and all message related stuff  // @@ -5528,7 +5495,9 @@ void LLAppViewer::disconnectViewer()  	}  	saveNameCache(); -	saveExperienceCache(); +    LLExperienceCache *expCache = LLExperienceCache::getIfExists(); +    if (expCache) +        expCache->cleanup();  	// close inventory interface, close all windows  	LLFloaterInventory::cleanup(); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 718871138e..e8a1ca036b 100755 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -122,9 +122,6 @@ public:      void loadNameCache();      void saveNameCache(); -	void loadExperienceCache(); -	void saveExperienceCache(); -  	void removeMarkerFiles();  	void removeDumpDir(); @@ -233,7 +230,6 @@ private:      void idle();       void idleShutdown();  	// update avatar SLID and display name caches -	void idleExperienceCache();  	void idleNameCache();      void idleNetwork(); diff --git a/indra/newview/llexperienceassociationresponder.cpp b/indra/newview/llexperienceassociationresponder.cpp index b50c81eedc..cd4a7516b1 100644 --- a/indra/newview/llexperienceassociationresponder.cpp +++ b/indra/newview/llexperienceassociationresponder.cpp @@ -83,7 +83,7 @@ void ExperienceAssociationResponder::httpSuccess()          return;      } -    LLExperienceCache::get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1)); +    LLExperienceCache::getInstance()->get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1));  } diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp index 197162487d..8a04f9e4cc 100644 --- a/indra/newview/llfloaterexperienceprofile.cpp +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -99,7 +99,7 @@ public:          if(params.size() != 2 || params[1].asString() != "profile")              return false; -        LLExperienceCache::get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); +        LLExperienceCache::getInstance()->get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1));          return true;      } @@ -288,8 +288,8 @@ BOOL LLFloaterExperienceProfile::postBuild()      if (mExperienceId.notNull())      { -        LLExperienceCache::fetch(mExperienceId, true); -        LLExperienceCache::get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback,  +        LLExperienceCache::getInstance()->fetch(mExperienceId, true); +        LLExperienceCache::getInstance()->get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback,              getDerivedHandle<LLFloaterExperienceProfile>(), _1));           LLViewerRegion* region = gAgent.getRegion(); @@ -799,8 +799,8 @@ void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content )      }      refreshExperience(*it); -    LLExperienceCache::insert(*it); -    LLExperienceCache::fetch(id, true); +    LLExperienceCache::getInstance()->insert(*it); +    LLExperienceCache::getInstance()->fetch(id, true);      if(mSaveCompleteAction==VIEW)      { diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 370d0f4f1b..714d8d0e8f 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -268,7 +268,7 @@ void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id)  	if (LLUUID::null != mExperienceID)  	{ -		const LLSD& experience = LLExperienceCache::get(mExperienceID); +        const LLSD& experience = LLExperienceCache::getInstance()->get(mExperienceID);  		std::stringstream desc;  		if(experience.isDefined()) diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp index fc4ee9862e..20fe0c52fa 100644 --- a/indra/newview/llpanelexperiencelisteditor.cpp +++ b/indra/newview/llpanelexperiencelisteditor.cpp @@ -183,7 +183,7 @@ void LLPanelExperienceListEditor::onItems()  		columns[0]["value"] = getString("loading");  		mItems->addElement(item); -		LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback,  +        LLExperienceCache::getInstance()->get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback,  			getDerivedHandle<LLPanelExperienceListEditor>(), _1));  	} diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp index df03ef7526..9329d900b1 100644 --- a/indra/newview/llpanelexperiencelog.cpp +++ b/indra/newview/llpanelexperiencelog.cpp @@ -140,7 +140,7 @@ void LLPanelExperienceLog::refresh()  				}  				const LLSD event = dayArray[i];  				LLUUID id = event[LLExperienceCache::EXPERIENCE_ID].asUUID(); -				const LLSD& experience = LLExperienceCache::get(id); +                const LLSD& experience = LLExperienceCache::getInstance()->get(id);  				if(experience.isUndefined()){  					waiting = true;  					waiting_id = id; @@ -168,7 +168,7 @@ void LLPanelExperienceLog::refresh()  	{  		mEventList->deleteAllItems();  		mEventList->setCommentText(getString("loading")); -		LLExperienceCache::get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); +        LLExperienceCache::getInstance()->get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this));  	}  	else  	{ diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp index c7a353a6af..7c19e32e7e 100644 --- a/indra/newview/llpanelexperiencepicker.cpp +++ b/indra/newview/llpanelexperiencepicker.cpp @@ -238,7 +238,7 @@ void LLPanelExperiencePicker::processResponse( const LLUUID& query_id, const LLS  	LLSD::array_const_iterator it = experiences.beginArray();  	for ( ; it != experiences.endArray(); ++it)  	{ -		LLExperienceCache::insert(*it); +        LLExperienceCache::getInstance()->insert(*it);  	}  	getChildView(BTN_RIGHT)->setEnabled(content.has("next_page_url")); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index a548d7b705..4f5d21b6be 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1326,7 +1326,7 @@ void LLLiveLSLEditor::buildExperienceList()  			position = ADD_TOP;  		} -		const LLSD& experience = LLExperienceCache::get(id); +        const LLSD& experience = LLExperienceCache::getInstance()->get(id);  		if(experience.isUndefined())  		{  			mExperiences->add(getString("loading"), id, position); @@ -1345,7 +1345,7 @@ void LLLiveLSLEditor::buildExperienceList()  	if(!foundAssociated )  	{ -		const LLSD& experience = LLExperienceCache::get(associated); +        const LLSD& experience = LLExperienceCache::getInstance()->get(associated);  		if(experience.isDefined())  		{  			std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); @@ -1366,7 +1366,7 @@ void LLLiveLSLEditor::buildExperienceList()  	if(last.notNull())  	{  		mExperiences->setEnabled(FALSE); -		LLExperienceCache::get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this));   +        LLExperienceCache::getInstance()->get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this));  	}  	else  	{ diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 46f75c4f57..361cc6c48b 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2821,9 +2821,10 @@ void LLStartUp::initNameCache()  void LLStartUp::initExperiences()  {    -    // just a get instance here.  Should trigger loading the cache. -    LLExperienceCache::getInstance(); -	LLAppViewer::instance()->loadExperienceCache(); +    // Should trigger loading the cache. +    LLExperienceCache::getInstance()->setCapabilityQuery( +        boost::bind(&LLAgent::getRegionCapability, &gAgent, _1)); +  	LLExperienceLog::instance().initialize();  } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 886725be79..4e1a86bb71 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6653,7 +6653,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data)  			else if(experienceid.notNull())  			{  				payload["experience"]=experienceid; -				LLExperienceCache::get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); +                LLExperienceCache::getInstance()->get(experienceid, boost::bind(process_script_experience_details, _1, args, payload));  				return;  			} | 
