summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llmessage/llexperiencecache.cpp214
-rw-r--r--indra/llmessage/llexperiencecache.h80
2 files changed, 168 insertions, 126 deletions
diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp
index d196d7da93..34c4210359 100644
--- a/indra/llmessage/llexperiencecache.cpp
+++ b/indra/llmessage/llexperiencecache.cpp
@@ -32,22 +32,18 @@
#include <set>
#include <map>
#include "boost/tokenizer.hpp"
+#include <boost/concept_check.hpp>
typedef std::map<LLUUID, LLUUID> KeyMap;
KeyMap privateToPublicKeyMap;
-void mapKeys(const LLSD& legacyKeys);
std::string sLookupURL;
-typedef std::map<LLUUID, std::string> ask_queue_t;
-ask_queue_t sAskQueue;
-
typedef std::map<LLUUID, F64> pending_queue_t;
pending_queue_t sPendingQueue;
-LLExperienceCache::cache_t sCache;
int sMaximumLookups = 10;
LLFrameTimer sRequestTimer;
@@ -55,16 +51,41 @@ LLFrameTimer sRequestTimer;
// Periodically clean out expired entries from the cache
LLFrameTimer sEraseExpiredTimer;
-// 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;
-
-bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age);
-void eraseExpired();
+//=========================================================================
+namespace LLExperienceCacheImpl
+{
+ bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age);
+ void mapKeys(const LLSD& legacyKeys);
+}
+//=========================================================================
+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::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::SLURL = "slurl";
+
+// should be in sync with experience-api/experiences/models.py
+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;
+
+// default values
+const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0;
+const S32 LLExperienceCache::DEFAULT_QUOTA = 128; // this is megabytes
//=========================================================================
LLExperienceCache::LLExperienceCache()
@@ -118,7 +139,7 @@ void LLExperienceCache::exportFile(std::ostream& ostr) const
// *TODO$: Rider: These three functions not seem to be used... it may be useful in testing.
void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration)
{
- mapKeys(legacyKeys);
+ LLExperienceCacheImpl::mapKeys(legacyKeys);
LLSD::array_const_iterator it = legacyKeys.beginArray();
for (/**/; it != legacyKeys.endArray(); ++it)
{
@@ -140,18 +161,6 @@ void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration)
}
}
-void LLExperienceCache::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))
- {
- privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()] = (*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID();
- }
- }
-}
-
LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_if_not_found)
{
if (private_key.isNull())
@@ -190,12 +199,10 @@ void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD&
signal_map_t::iterator sig_it = sSignalMap.find(public_key);
if (sig_it != sSignalMap.end())
{
- callback_signal_t* signal = sig_it->second;
+ signal_ptr signal = sig_it->second;
(*signal)(experience);
sSignalMap.erase(public_key);
-
- delete signal;
}
}
@@ -236,60 +243,6 @@ static const std::string MAX_AGE("max-age");
static const boost::char_separator<char> EQUALS_SEPARATOR("=");
static const boost::char_separator<char> COMMA_SEPARATOR(",");
-bool max_age_from_cache_control(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;
- tokenizer directives(cache_control, COMMA_SEPARATOR);
-
- tokenizer::iterator token_it = directives.begin();
- for ( ; token_it != directives.end(); ++token_it)
- {
- // Tokens may have leading or trailing whitespace
- std::string token = *token_it;
- LLStringUtil::trim(token);
-
- if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
- {
- // ...this token starts with max-age, so let's chop it up by "="
- tokenizer subtokens(token, EQUALS_SEPARATOR);
- tokenizer::iterator subtoken_it = subtokens.begin();
-
- // Must have a token
- if (subtoken_it == subtokens.end()) return false;
- std::string subtoken = *subtoken_it;
-
- // Must exactly equal "max-age"
- LLStringUtil::trim(subtoken);
- if (subtoken != MAX_AGE) return false;
-
- // Must have another token
- ++subtoken_it;
- if (subtoken_it == subtokens.end()) return false;
- subtoken = *subtoken_it;
-
- // Must be a valid integer
- // *NOTE: atoi() returns 0 for invalid values, so we have to
- // check the string first.
- // *TODO: Do servers ever send "0000" for zero? We don't handle it
- LLStringUtil::trim(subtoken);
- if (subtoken == "0")
- {
- *max_age = 0;
- return true;
- }
- S32 val = atoi( subtoken.c_str() );
- if (val > 0 && val < S32_MAX)
- {
- *max_age = val;
- return true;
- }
- return false;
- }
- }
- return false;
-}
-
class LLExperienceResponder : public LLHTTPClient::Responder
{
@@ -435,7 +388,6 @@ void LLExperienceCache::requestExperiences()
ostr << sLookupURL << "?page_size=" << PAGE_SIZE;
-
int request_count = 0;
while(!sAskQueue.empty() && request_count < sMaximumLookups)
{
@@ -503,7 +455,6 @@ bool LLExperienceCache::hasLookupURL()
void LLExperienceCache::idle()
{
-
const F32 SECS_BETWEEN_REQUESTS = 0.1f;
if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS))
{
@@ -517,7 +468,6 @@ void LLExperienceCache::idle()
eraseExpired();
}
-
if(!sAskQueue.empty())
{
requestExperiences();
@@ -568,7 +518,6 @@ void LLExperienceCache::eraseExpired()
}
}
}
-
bool LLExperienceCache::fetch(const LLUUID& key, bool refresh/* = true*/)
{
@@ -594,10 +543,12 @@ void LLExperienceCache::insert(const LLSD& experience_data)
}
}
-static LLSD empty;
const LLSD& LLExperienceCache::get(const LLUUID& key)
{
- if(key.isNull()) return empty;
+ static const LLSD empty;
+
+ if(key.isNull())
+ return empty;
cache_t::const_iterator it = sCache.find(key);
if (it != sCache.end())
@@ -609,9 +560,10 @@ const LLSD& LLExperienceCache::get(const LLUUID& key)
return empty;
}
-void LLExperienceCache::get(const LLUUID& key, callback_slot_t slot)
+void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::Callback_t slot)
{
- if(key.isNull()) return;
+ if(key.isNull())
+ return;
cache_t::const_iterator it = sCache.find(key);
if (it != sCache.end())
@@ -626,12 +578,20 @@ void LLExperienceCache::get(const LLUUID& key, callback_slot_t slot)
fetch(key);
+ 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));
+ if (!result.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
- callback_signal_t* signal = new callback_signal_t();
+ signal_ptr signal = signal_ptr(new callback_signal_t());
signal->connect(slot);
sSignalMap[key] = signal;
}
@@ -641,6 +601,76 @@ void LLExperienceCache::get(const LLUUID& key, callback_slot_t slot)
callback_signal_t* signal = sig_it->second;
signal->connect(slot);
}
+#endif
+}
+
+//=========================================================================
+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))
+ {
+ privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()] = (*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID();
+ }
+ }
}
+bool LLExperienceCacheImpl::max_age_from_cache_control(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;
+ tokenizer directives(cache_control, COMMA_SEPARATOR);
+
+ tokenizer::iterator token_it = directives.begin();
+ for ( ; token_it != directives.end(); ++token_it)
+ {
+ // Tokens may have leading or trailing whitespace
+ std::string token = *token_it;
+ LLStringUtil::trim(token);
+
+ if (token.compare(0, MAX_AGE.size(), MAX_AGE) == 0)
+ {
+ // ...this token starts with max-age, so let's chop it up by "="
+ tokenizer subtokens(token, EQUALS_SEPARATOR);
+ tokenizer::iterator subtoken_it = subtokens.begin();
+
+ // Must have a token
+ if (subtoken_it == subtokens.end()) return false;
+ std::string subtoken = *subtoken_it;
+
+ // Must exactly equal "max-age"
+ LLStringUtil::trim(subtoken);
+ if (subtoken != MAX_AGE) return false;
+
+ // Must have another token
+ ++subtoken_it;
+ if (subtoken_it == subtokens.end()) return false;
+ subtoken = *subtoken_it;
+
+ // Must be a valid integer
+ // *NOTE: atoi() returns 0 for invalid values, so we have to
+ // check the string first.
+ // *TODO: Do servers ever send "0000" for zero? We don't handle it
+ LLStringUtil::trim(subtoken);
+ if (subtoken == "0")
+ {
+ *max_age = 0;
+ return true;
+ }
+ S32 val = atoi( subtoken.c_str() );
+ if (val > 0 && val < S32_MAX)
+ {
+ *max_age = val;
+ return true;
+ }
+ return false;
+ }
+ }
+ return false;
+}
+
+
+
diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h
index 8a55719443..8da038a8c3 100644
--- a/indra/llmessage/llexperiencecache.h
+++ b/indra/llmessage/llexperiencecache.h
@@ -56,10 +56,45 @@ public:
private:
// Callback types for get()
-// typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t;
- typedef boost::signals2::signal < Callback_t > callback_signal_t;
- typedef std::map<LLUUID, LLSD> cache_t;
-
+ typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t;
+ typedef boost::shared_ptr<callback_signal_t> signal_ptr;
+ // 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, signal_ptr> signal_map_t;
+ typedef std::map<LLUUID, LLSD> cache_t;
+
+ typedef std::set<LLUUID> ask_queue_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();
@@ -70,36 +105,13 @@ private:
//--------------------------------------------
void processExperience(const LLUUID& public_key, const LLSD& experience);
-
- const std::string PRIVATE_KEY = "private_id";
- const std::string MISSING = "DoesNotExist";
-
- const std::string AGENT_ID = "agent_id";
- const std::string GROUP_ID = "group_id";
- const std::string EXPERIENCE_ID = "public_id";
- const std::string NAME = "name";
- const std::string PROPERTIES = "properties";
- const std::string EXPIRES = "expiration";
- const std::string DESCRIPTION = "description";
- const std::string QUOTA = "quota";
- const std::string MATURITY = "maturity";
- const std::string METADATA = "extended_metadata";
- const std::string SLURL = "slurl";
-
-
- // should be in sync with experience-api/experiences/models.py
- const int PROPERTY_INVALID = 1 << 0;
- const int PROPERTY_PRIVILEGED = 1 << 3;
- const int PROPERTY_GRID = 1 << 4;
- const int PROPERTY_PRIVATE = 1 << 5;
- const int PROPERTY_DISABLED = 1 << 6;
- const int PROPERTY_SUSPENDED = 1 << 7;
-
- // default values
- const static F64 DEFAULT_EXPIRATION = 600.0;
- const static S32 DEFAULT_QUOTA = 128; // this is megabytes
-
-
+//--------------------------------------------
+ cache_t sCache;
+ signal_map_t sSignalMap;
+ ask_queue_t sAskQueue;
+
+ void eraseExpired();
+
void setLookupURL(const std::string& lookup_url);
bool hasLookupURL();