diff options
| author | dolphin@dolphin-THINK.lindenlab.com <dolphin@dolphin-THINK.lindenlab.com> | 2012-11-19 08:21:04 -0800 | 
|---|---|---|
| committer | dolphin@dolphin-THINK.lindenlab.com <dolphin@dolphin-THINK.lindenlab.com> | 2012-11-19 08:21:04 -0800 | 
| commit | ad3f7ea13f0f7cdaa8f4a41d2bc2044620cdfdfb (patch) | |
| tree | 95c919bb29468d0ad9c71457ea8a8c306dd747f1 /indra/llmessage | |
| parent | 185169cbbecebe2a35dbd937d6fb4e0a30fa1832 (diff) | |
| parent | 2cde962d5db94baf860eb94fecaf9671548b2c53 (diff) | |
Merge
Diffstat (limited to 'indra/llmessage')
| -rw-r--r-- | indra/llmessage/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llmessage/llexperiencecache.cpp | 313 | ||||
| -rw-r--r-- | indra/llmessage/llexperiencecache.h | 71 | 
3 files changed, 386 insertions, 0 deletions
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index d98781e9e6..9974d103a2 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -38,6 +38,7 @@ set(llmessage_SOURCE_FILES      llcurl.cpp      lldatapacker.cpp      lldispatcher.cpp +	llexperiencecache.cpp      llfiltersd2xmlrpc.cpp      llhost.cpp      llhttpassetstorage.cpp @@ -128,6 +129,7 @@ set(llmessage_HEADER_FILES      lldbstrings.h      lldispatcher.h      lleventflags.h +	llexperiencecache.h      llfiltersd2xmlrpc.h      llfollowcamparams.h      llhost.h diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp new file mode 100644 index 0000000000..0d8f76c7e2 --- /dev/null +++ b/indra/llmessage/llexperiencecache.cpp @@ -0,0 +1,313 @@ +/**  + * @file llexperiencecache.cpp + * @brief llexperiencecache and related class definitions + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llavatarname.h" +#include "llframetimer.h" +#include "llhttpclient.h" +#include "llsdserialize.h" +#include <set> +#include <map> + +#include "llexperiencecache.h" + + + +namespace LLExperienceCache +{ +	bool sRunning = false; +	std::string sLookupURL; + +	typedef std::set<LLUUID> ask_queue_t; +	ask_queue_t sAskQueue; + +	typedef std::map<LLUUID, F64> pending_queue_t; +	pending_queue_t sPendingQueue; + + +	cache_t sCache; + +	LLFrameTimer sRequestTimer; + + + +	void processExperience( const LLUUID& agent_id, const LLExperienceData& experience, bool add_to_cache )  +	{ +		if(add_to_cache) +		{ +			sCache[agent_id]=experience; + +			sPendingQueue.erase(agent_id); + + +			//signal +		} +	} + +	void initClass( bool running ) +	{ +		sRunning = false; +	} + +	const cache_t& getCached() +	{ +		return sCache; +	} + + + +	void importFile(std::istream& istr) +	{ +		LLSD data; +		S32 parse_count = LLSDSerialize::fromXMLDocument(data, istr); +		if(parse_count < 1) return; + +		LLSD agents = data["agents"]; + +		LLUUID agent_id; +		LLExperienceData experience; +		LLSD::map_const_iterator it = agents.beginMap(); +		for(; it != agents.endMap() ; ++it) +		{ +			agent_id.set(it->first); +			experience.fromLLSD( it->second); +			sCache[agent_id]=experience; +		} + +		LL_INFOS("ExperienceCache") << "loaded " << sCache.size() << LL_ENDL; +	} + +	void exportFile(std::ostream& ostr) +	{ +		LLSD agents; + +		cache_t::const_iterator it =sCache.begin(); +		for( ; it != sCache.end() ; ++it) +		{ +			agents[it->first.asString()] = it->second.asLLSD(); +		} + +		LLSD data; +		data["agents"] = agents; + +		LLSDSerialize::toPrettyXML(data, ostr); +	} + +	class LLExperienceResponder : public LLHTTPClient::Responder +	{ +	public: +		LLExperienceResponder(const std::vector<LLUUID>& agent_ids) +			:mAgentIds(agent_ids) +		{ + +		} + +		virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content) +		{ +			mHeaders = content; +		} + +		virtual void result(const LLSD& content) +		{ +			LLSD agents = content["agents"]; +			LLSD::array_const_iterator it = agents.beginArray(); +			for( /**/ ; it != agents.endArray(); ++it) +			{ +				const LLSD& row = *it; +				LLUUID agent_id = row["id"].asUUID(); + +				LLExperienceData experience; + +				if(experience.fromLLSD(row)) +				{ +					LL_DEBUGS("ExperienceCache") << __FUNCTION__ << "Received result for " << agent_id  +						<< "display '" << experience.mDisplayName << "'" << LL_ENDL ; + +					processExperience(agent_id, experience, true); +				} +			} + +			LLSD unresolved_agents = content["bad_ids"]; +			S32 num_unresolved = unresolved_agents.size(); +			if(num_unresolved > 0) +			{ +				LL_DEBUGS("ExperienceCache") << __FUNCTION__ << "Ignoreing " << num_unresolved  +					<< " bad ids" << LL_ENDL ; +			} + +			LL_DEBUGS("ExperienceCache") << __FUNCTION__ << sCache.size() << " cached experiences" << LL_ENDL; +		} + +	private: +		std::vector<LLUUID> mAgentIds; +		LLSD mHeaders; +	}; + +	void requestExperiences()  +	{ +		if(sAskQueue.empty()) +			return; + +		F64 now = LLFrameTimer::getTotalSeconds(); + +		const U32 NAME_URL_MAX = 4096; +		const U32 NAME_URL_SEND_THRESHOLD = 3000; + +		std::string url; +		url.reserve(NAME_URL_MAX); + +		std::vector<LLUUID> agent_ids; +		agent_ids.reserve(128); + +		url += sLookupURL; + +		std::string arg="?ids="; + +		for(ask_queue_t::const_iterator it = sAskQueue.begin(); it != sAskQueue.end() ; ++it) +		{ +			const LLUUID& agent_id = *it; +		 +			url += arg; +			url += agent_id.asString(); +			agent_ids.push_back(agent_id); + +			sPendingQueue[agent_id] = now; + +			arg[0]='&'; + +			if(url.size() > NAME_URL_SEND_THRESHOLD) +			{ +				 LLHTTPClient::get(url, new LLExperienceResponder(agent_ids)); +				 url = sLookupURL; +				 arg[0]='?'; +				 agent_ids.clear(); +			} +		} + +		if(url.size() > sLookupURL.size()) +		{ +			LLHTTPClient::get(url, new LLExperienceResponder(agent_ids)); +		} + +		sAskQueue.clear(); +	} + +	bool 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()) +		{ +			F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS; +			isPending = (it->second > expire_time); +		} + +		return isPending; +	} + + +	void setLookupURL( const std::string& lookup_url ) +	{ +		sLookupURL = lookup_url; +	} + +	bool hasLookupURL() +	{ +		return !sLookupURL.empty(); +	} + +	void idle() +	{ +		sRunning = true; + +		if(!sAskQueue.empty()) +		{ +			requestExperiences(); +		} +	} + +	void erase( const LLUUID& agent_id ) +	{ +		sCache.erase(agent_id); +	} + +	void fetch( const LLUUID& agent_id )  +	{ +		LL_DEBUGS("ExperienceCache") << __FUNCTION__ << "queue request for agent" << agent_id << LL_ENDL ; +		sAskQueue.insert(agent_id); +	} + +	void insert( const LLUUID& agent_id, const LLExperienceData& experience_data ) +	{ +		sCache[agent_id]=experience_data; +	} + +	bool get( const LLUUID& agent_id, LLExperienceData* experience_data ) +	{ +		if(sRunning)  +		{ + +			cache_t::const_iterator it = sCache.find(agent_id); +			if (it != sCache.end()) +			{ +				llassert(experience_data); +				*experience_data = it->second; +				return true; +			} +		} +		 +		if(!isRequestPending(agent_id)) +		{ +			fetch(agent_id); +		} + +		return false; +	} + + +} + +bool LLExperienceData::fromLLSD( const LLSD& sd ) +{ +	mDisplayName = sd["display_name"].asString(); +	mDescription = sd["username"].asString(); + +	if(mDisplayName.empty() || mDescription.empty()) return false; + +	mDescription += " % Hey, this is a description!"; +	return true; +} + +LLSD LLExperienceData::asLLSD() const +{ +	LLSD sd; +	sd["display_name"] = mDisplayName; +	sd["username"] = mDescription.substr(0, llmin(mDescription.size(),mDescription.find(" %"))); +	return sd; +} diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h new file mode 100644 index 0000000000..799cdea13a --- /dev/null +++ b/indra/llmessage/llexperiencecache.h @@ -0,0 +1,71 @@ +/**  + * @file llexperiencecache.h + * @brief Caches information relating to experience keys + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2012, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + + + +#ifndef LL_LLEXPERIENCECACHE_H +#define LL_LLEXPERIENCECACHE_H + +#include <string> + +class LLUUID; + + +class LLExperienceData +{ +public: +	bool fromLLSD(const LLSD& sd); +	LLSD asLLSD() const; + + +	std::string mDisplayName; +	std::string mDescription; +}; + + + +namespace LLExperienceCache +{ +	void setLookupURL(const std::string& lookup_url); +	bool hasLookupURL(); + + +	void idle(); +	void exportFile(std::ostream& ostr); +	void importFile(std::istream& istr); +	void initClass(bool running); + +	void erase(const LLUUID& agent_id); +	void fetch(const LLUUID& agent_id); +	void insert(const LLUUID& agent_id, const LLExperienceData& experience_data); +	bool get(const LLUUID& agent_id, LLExperienceData* experience_data); + +	typedef std::map<LLUUID, LLExperienceData> cache_t; + +	const cache_t& getCached(); +}; + +#endif // LL_LLEXPERIENCECACHE_H  | 
