diff options
| author | Christian Goetze <cg@lindenlab.com> | 2009-07-01 00:22:05 +0000 | 
|---|---|---|
| committer | Christian Goetze <cg@lindenlab.com> | 2009-07-01 00:22:05 +0000 | 
| commit | e588d1f28419745ee1e1ee98dc1852e0364a4088 (patch) | |
| tree | 8a3546576e0d5a8f0cf32cca68d0913f1061d523 /indra/llmessage | |
| parent | 5f4c09fa1f4b09126e1a16e78044c64e97828530 (diff) | |
svn merge -r125825:125901 svn+ssh://svn.lindenlab.com/svn/user/cg/qar-1654
QAR-1654 merge completed.
Diffstat (limited to 'indra/llmessage')
| -rw-r--r-- | indra/llmessage/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | indra/llmessage/llcachename.cpp | 226 | ||||
| -rw-r--r-- | indra/llmessage/llcachename.h | 6 | ||||
| -rw-r--r-- | indra/llmessage/llhttpclientadapter.cpp | 2 | ||||
| -rw-r--r-- | indra/llmessage/llhttpclientadapter.h | 2 | ||||
| -rw-r--r-- | indra/llmessage/llhttpclientinterface.h | 2 | ||||
| -rw-r--r-- | indra/llmessage/llmessagesenderinterface.h | 2 | ||||
| -rw-r--r-- | indra/llmessage/llregionpresenceverifier.cpp | 86 | ||||
| -rw-r--r-- | indra/llmessage/llregionpresenceverifier.h | 39 | ||||
| -rw-r--r-- | indra/llmessage/llstoredmessage.cpp | 2 | ||||
| -rw-r--r-- | indra/llmessage/llstoredmessage.h | 2 | ||||
| -rw-r--r-- | indra/llmessage/llthrottle.cpp | 25 | ||||
| -rw-r--r-- | indra/llmessage/llthrottle.h | 2 | ||||
| -rw-r--r-- | indra/llmessage/llurlrequest.cpp | 54 | ||||
| -rw-r--r-- | indra/llmessage/llurlrequest.h | 8 | ||||
| -rw-r--r-- | indra/llmessage/tests/llregionpresenceverifier_test.cpp | 111 | 
16 files changed, 433 insertions, 138 deletions
| diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 88f83ba78e..81e518cf6e 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -221,6 +221,7 @@ IF (NOT LINUX AND VIEWER)        # llhttpclientadapter.cpp        lltrustedmessageservice.cpp        lltemplatemessagedispatcher.cpp +      llregionpresenceverifier.cpp        )      LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}") @@ -228,3 +229,4 @@ IF (NOT LINUX AND VIEWER)      # Don't make llmessage depend on llsdmessage_test because ADD_COMM_BUILD_TEST depends on llmessage!      # ADD_COMM_BUILD_TEST(llsdmessage "" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py")  ENDIF (NOT LINUX AND VIEWER) + diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 799bc83e20..82186fc503 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -76,11 +76,13 @@ public:  	LLCacheNameEntry();  public: -	bool mIsGroup; -	U32 mCreateTime;	// unix time_t -	std::string mFirstName; -	std::string mLastName; -	std::string mGroupName; +	bool isUnknown()			{ return (mFirstName.empty() +										  || mFirstName == std::string("(???)"));	}; + +	bool mIsGroup;				// true if this is a group ID/name +	U32 mCreateTime;			// unix time_t +	std::string mFirstName;		// Doubles as the group name +	std::string mLastName;		// Will be "" for groups  };  LLCacheNameEntry::LLCacheNameEntry() @@ -162,7 +164,7 @@ void ReplySender::send(const LLUUID& id,  	mMsg->addUUIDFast(_PREHASH_ID, id);  	if(mCurrIsGroup)  	{ -		mMsg->addStringFast(_PREHASH_GroupName, entry.mGroupName); +		mMsg->addStringFast(_PREHASH_GroupName, entry.mFirstName);  	}  	else  	{ @@ -222,6 +224,7 @@ public:  	void processPendingReplies();  	void sendRequest(const char* msg_name, const AskQueue& queue);  	bool isRequestPending(const LLUUID& id); +	void makeNameRequestForID(const LLUUID& id, bool isGroup, LLHost & fromHost);  	// Message system callbacks.  	void processUUIDRequest(LLMessageSystem* msg, bool isGroup); @@ -389,6 +392,7 @@ void LLCacheName::importFile(LLFILE* fp)  		entry->mCreateTime = create_time;  		entry->mFirstName = firstname;  		entry->mLastName = lastname; +		//llinfos << "Adding entry from file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;  		impl.mCache[id] = entry;  		count++; @@ -425,6 +429,7 @@ bool LLCacheName::importFile(std::istream& istr)  		entry->mCreateTime = ctime;  		entry->mFirstName = agent[FIRST].asString();  		entry->mLastName = agent[LAST].asString(); +		//llinfos << "Adding name entry from XML file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;  		impl.mCache[id] = entry;  		++count; @@ -445,7 +450,9 @@ bool LLCacheName::importFile(std::istream& istr)  		LLCacheNameEntry* entry = new LLCacheNameEntry();  		entry->mIsGroup = true;  		entry->mCreateTime = ctime; -		entry->mGroupName = group[NAME].asString(); +		entry->mFirstName = group[NAME].asString(); +		entry->mLastName = ""; +		//llinfos << "Adding group entry from XML file for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl;  		impl.mCache[id] = entry;  		++count;  	} @@ -463,32 +470,32 @@ void LLCacheName::exportFile(std::ostream& ostr)  		// Only write entries for which we have valid data.  		LLCacheNameEntry* entry = iter->second;  		if(!entry -		   || (std::string::npos != entry->mFirstName.find('?')) -		   || (std::string::npos != entry->mGroupName.find('?'))) -		{ +		   || entry->isUnknown()) +		{	// No entry, or user or group name is unknown  			continue;  		}  		// store it  		LLUUID id = iter->first;  		std::string id_str = id.asString(); -		if(!entry->mFirstName.empty() && !entry->mLastName.empty()) -		{ +		if(entry->mIsGroup) +		{	// Save group name and ID +			data[GROUPS][id_str][NAME] = entry->mFirstName; +			data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime; +		} +		else if(!entry->mLastName.empty()) +		{	// Save user names and ID  			data[AGENTS][id_str][FIRST] = entry->mFirstName;  			data[AGENTS][id_str][LAST] = entry->mLastName;  			data[AGENTS][id_str][CTIME] = (S32)entry->mCreateTime;  		} -		else if(entry->mIsGroup && !entry->mGroupName.empty()) -		{ -			data[GROUPS][id_str][NAME] = entry->mGroupName; -			data[GROUPS][id_str][CTIME] = (S32)entry->mCreateTime; -		}  	}  	LLSDSerialize::toPrettyXML(data, ostr);  } +// DO NOT CALL THIS FOR GROUP NAMES  BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& last)  {  	if(id.isNull()) @@ -511,11 +518,11 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las  		last.clear();  		if (!impl.isRequestPending(id))  		{ +			//llinfos << "**** adding name req for " << id << llendl;  			impl.mAskNameQueue.insert(id);  		}	 -		return FALSE;  	} - +	return FALSE;  }  BOOL LLCacheName::getFullName(const LLUUID& id, std::string& fullname) @@ -535,7 +542,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)  	}  	LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache,id); -	if (entry && entry->mGroupName.empty()) +	if (entry && entry->mFirstName.empty())  	{  		// COUNTER-HACK to combat James' HACK in exportFile()...  		// this group name was loaded from a name cache that did not @@ -546,7 +553,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)  	if (entry)  	{ -		group = entry->mGroupName; +		group = entry->mFirstName;  		return TRUE;  	}  	else  @@ -562,7 +569,7 @@ BOOL LLCacheName::getGroupName(const LLUUID& id, std::string& group)  // TODO: Make the cache name callback take a SINGLE std::string,  // not a separate first and last name. -void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data) +void LLCacheName::getNameFromUUID(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data)  {  	if(id.isNull())  	{ @@ -573,15 +580,8 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb  	LLCacheNameEntry* entry = get_ptr_in_map(impl.mCache, id );  	if (entry)  	{ -		// id found in map therefore we can call the callback immediately. -		if (entry->mIsGroup) -		{ -			callback(id, entry->mGroupName, "", entry->mIsGroup, user_data); -		} -		else -		{ -			callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data); -		} +		// id found in map therefore we can call the callback immediately.  mLastName will be empty for groups +		callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data);  	}  	else  	{ @@ -590,13 +590,17 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb  		{  			if (is_group)  			{ +				//llinfos << "Group queued for " << id << llendl;  				impl.mAskGroupQueue.insert(id);  			}  			else  			{ +				//llinfos << "Name queued for " << id << llendl;  				impl.mAskNameQueue.insert(id);  			}  		} + +		// There may be multiple replies for the same ID request  		impl.mReplyQueue.push_back(PendingReply(id, callback, user_data));  	}  } @@ -661,7 +665,7 @@ void LLCacheName::dump()  		{  			llinfos  				<< iter->first << " = (group) " -				<< entry->mGroupName +				<< entry->mFirstName  				<< " @ " << entry->mCreateTime  				<< llendl;  		} @@ -715,17 +719,7 @@ void LLCacheName::Impl::processPendingReplies()  		if (it->mCallback)  		{ -			if (!entry->mIsGroup) -			{ -				(it->mCallback)(it->mID, -					entry->mFirstName, entry->mLastName, -					FALSE, it->mData); -			} -			else { -				(it->mCallback)(it->mID, -					entry->mGroupName, "", -					TRUE, it->mData); -			} +			(it->mCallback)(it->mID, entry->mFirstName, entry->mLastName, entry->mIsGroup, it->mData);  		}  	} @@ -768,10 +762,12 @@ void LLCacheName::Impl::sendRequest(  		if(start_new_message)  		{  			start_new_message = false; +			//llinfos << "newMessageFast : " << msg_name << llendl;  			mMsg->newMessageFast(msg_name);  		}  		mMsg->nextBlockFast(_PREHASH_UUIDNameBlock);  		mMsg->addUUIDFast(_PREHASH_ID, (*it)); +		//llinfos << " asking for ID: " << (*it) << llendl;  		if(mMsg->isSendFullFast(_PREHASH_UUIDNameBlock))  		{ @@ -837,38 +833,102 @@ void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup)  		{  			if (isGroup != entry->mIsGroup)  			{ -				llwarns << "LLCacheName - Asked for " -						<< (isGroup ? "group" : "user") << " name, " -						<< "but found " -						<< (entry->mIsGroup ? "group" : "user") -						<< ": " << id << llendl; +				if (entry->isUnknown()) +				{ +					Cache::iterator doomediter = mCache.find(id); +					if (doomediter != mCache.end()) +					{	// Kill existing unknown entry +						llwarns << "LLCacheName - Asked for " +								<< (isGroup ? "group" : "user") << " name, " +								<< "but found unknown " +								<< (entry->mIsGroup ? "group" : "user") +								<< " entry for: " << id  +								<< ", deleting bad entry" +								<< llendl; + +						delete entry; +						entry = NULL; +						mCache.erase(doomediter); + +						// Request it with (hopefully) the correct type +						makeNameRequestForID(id,isGroup,fromHost); +					} +				} +				else if (isGroup) +				{ +					llwarns << "LLCacheName - Asked for group name, but found user: " +							<< id  +							<< " named "  +							<< entry->mFirstName << " " << entry->mLastName  +							<< llendl; +				} +				else +				{ +					llwarns << "LLCacheName - Asked for user name, but found group: " +							<< id  +							<< " named "  +							<< entry->mFirstName +							<< llendl; +				}  			}  			else  			{  				// ...it's in the cache, so send it as the reply  				sender.send(id, *entry, fromHost); -			} -		} -		else -		{ -			if (!isRequestPending(id)) -			{ + +				/*  				if (isGroup)  				{ -					mAskGroupQueue.insert(id); +					llinfos << "Group ID " << id  +						<< " name " << entry->mFirstName +						<< " was already in cache" << llendl;  				}  				else  				{ -					mAskNameQueue.insert(id); +					llinfos << "Agent ID " << id  +						<< " name " << entry->mFirstName << " " << entry->mLastName  +						<< " was already in cache" << llendl;  				} +				*/  			} -			 -			mReplyQueue.push_back(PendingReply(id, fromHost)); +		} +		else +		{	/* +			if (isGroup) +			{ +				llinfos << "Group ID " << id << " is not in cache" << llendl; +			} +			else +			{ +				llinfos << "Agent ID " << id << " is not in cache" << llendl; +			} +			*/ +			makeNameRequestForID(id,isGroup,fromHost);  		}  	}  } +void LLCacheName::Impl::makeNameRequestForID(const LLUUID& id, bool isGroup, LLHost & fromHost) +{ +	if (!isRequestPending(id)) +	{ +		if (isGroup) +		{ +			//llinfos << "Adding group request for " << id << llendl; +			mAskGroupQueue.insert(id); +		} +		else +		{ +			//llinfos << "Adding name request for " << id << llendl; +			mAskNameQueue.insert(id); +		} +	} +	 +	// There may be multiple replys for the same ID request +	mReplyQueue.push_back(PendingReply(id, fromHost)); +} +  void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)  { @@ -878,35 +938,53 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup)  		LLUUID id;  		msg->getUUIDFast(_PREHASH_UUIDNameBlock, _PREHASH_ID, id, i);  		LLCacheNameEntry* entry = get_ptr_in_map(mCache, id); +		bool add_new_entry_to_cache = false;  		if (!entry)  		{  			entry = new LLCacheNameEntry; -			mCache[id] = entry; +			add_new_entry_to_cache = true;  		} +		// Remove ID from pending queue  		mPendingQueue.erase(id); -		entry->mIsGroup = isGroup; -		entry->mCreateTime = (U32)time(NULL); -		if (!isGroup) -		{ -			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, entry->mFirstName, i); -			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName,  entry->mLastName, i); +		std::string first_name; +		std::string last_name; +		if (isGroup) +		{	// Group +			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, first_name, i); +			LLStringFn::replace_ascii_controlchars(first_name, LL_UNKNOWN_CHAR);  		}  		else -		{	// is group -			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_GroupName, entry->mGroupName, i); -			LLStringFn::replace_ascii_controlchars(entry->mGroupName, LL_UNKNOWN_CHAR); +		{	// User +			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_FirstName, first_name, i); +			msg->getStringFast(_PREHASH_UUIDNameBlock, _PREHASH_LastName, last_name, i);  		} - -		if (!isGroup) -		{ -			notifyObservers(id, entry->mFirstName, entry->mLastName, FALSE); +	 +		if (!add_new_entry_to_cache && +			(entry->mFirstName != first_name || +				entry->mLastName != last_name || +				entry->mIsGroup != isGroup)) +		{	// Hmmm, we already had an different entry for this ID.  Let's see what happened... +			llwarns << "Replacing existing entry in name cache for id " << id +				<< " first name was " << entry->mFirstName << ", now " << first_name +				<< " last name was " << entry->mLastName << ", now " << last_name +				<< " group flag was " << (S32) entry->mIsGroup << ", now " << (S32) isGroup +				<< llendl;  		} -		else + +		entry->mFirstName = first_name; +		entry->mLastName = last_name; +		entry->mIsGroup = isGroup; +		entry->mCreateTime = (U32)time(NULL); + +		if (add_new_entry_to_cache)  		{ -			notifyObservers(id, entry->mGroupName, "", TRUE); +			//llinfos << "Adding entry for " << entry->mFirstName << " " << entry->mLastName << ", id " << id << llendl; +			mCache[id] = entry;  		} + +		notifyObservers(id, entry->mFirstName, entry->mLastName, isGroup);  	}  } diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index 2757b86a7c..bfa116ad4a 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -89,12 +89,8 @@ public:  	// If the data is currently available, may call the callback immediatly  	// otherwise, will request the data, and will call the callback when  	// available.  There is no garuntee the callback will ever be called. -	void get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL); +	void getNameFromUUID(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL); -	// LEGACY -	void getName(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL) -			{ get(id, FALSE, callback, user_data); } -  	// This method needs to be called from time to time to send out  	// requests.  	void processPending(); diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp index bbb56960df..5236a52164 100644 --- a/indra/llmessage/llhttpclientadapter.cpp +++ b/indra/llmessage/llhttpclientadapter.cpp @@ -1,5 +1,5 @@  /**  - * @file  + * @file llhttpclientadapter.cpp   * @brief    *   * $LicenseInfo:firstyear=2009&license=viewergpl$ diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h index d5f3aeaf2c..c489dca32d 100644 --- a/indra/llmessage/llhttpclientadapter.h +++ b/indra/llmessage/llhttpclientadapter.h @@ -1,5 +1,5 @@  /**  - * @file  + * @file llhttpclientadepter.h   * @brief    *   * $LicenseInfo:firstyear=2008&license=viewergpl$ diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h index 1f13d46447..61826cc4b4 100644 --- a/indra/llmessage/llhttpclientinterface.h +++ b/indra/llmessage/llhttpclientinterface.h @@ -1,5 +1,5 @@  /**  - * @file  + * @file llhttpclientinterface.h   * @brief    *   * $LicenseInfo:firstyear=2008&license=viewergpl$ diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h index 4082666339..d98d891563 100644 --- a/indra/llmessage/llmessagesenderinterface.h +++ b/indra/llmessage/llmessagesenderinterface.h @@ -1,5 +1,5 @@  /**  - * @file  + * @file llmessagesenderinterface.h   * @brief    *   * $LicenseInfo:firstyear=2008&license=viewergpl$ diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp index 552cf4cbdb..08c12f90da 100644 --- a/indra/llmessage/llregionpresenceverifier.cpp +++ b/indra/llmessage/llregionpresenceverifier.cpp @@ -1,5 +1,5 @@  /**  - * @file  + * @file llregionpresenceverifier.cpp   * @brief    *   * $LicenseInfo:firstyear=2008&license=viewergpl$ @@ -25,11 +25,40 @@  #include "net.h"  #include "message.h" +namespace boost +{ +	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p) +	{ +		++p->mReferenceCount; +	} +	 +	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p) +	{ +		if(p && 0 == --p->mReferenceCount) +		{ +			delete p; +		} +	} +}; -LLRegionPresenceVerifier::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data) +LLRegionPresenceVerifier::Response::~Response()  {  } +LLRegionPresenceVerifier::RegionResponder::RegionResponder(const std::string& +														   uri, +														   ResponsePtr data, +														   S32 retry_count) : +	mUri(uri), +	mSharedData(data), +	mRetryCount(retry_count) +{ +} + +//virtual +LLRegionPresenceVerifier::RegionResponder::~RegionResponder() +{ +}  void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)  { @@ -42,26 +71,32 @@ void LLRegionPresenceVerifier::RegionResponder::result(const LLSD& content)  	std::stringstream uri;  	uri << "http://" << destination.getString() << "/state/basic/"; -	mSharedData->getHttpClient().get(uri.str(), new VerifiedDestinationResponder(mSharedData, content)); +	mSharedData->getHttpClient().get( +		uri.str(), +		new VerifiedDestinationResponder(mUri, mSharedData, content, mRetryCount));  } -void LLRegionPresenceVerifier::RegionResponder::completed( -	U32 status, -	const std::string& reason, -	const LLSD& content) +void LLRegionPresenceVerifier::RegionResponder::error(U32 status, +													 const std::string& reason)  { -	LLHTTPClient::Responder::completed(status, reason, content); -	 -	mSharedData->onCompletedRegionRequest(); +	// TODO: babbage: distinguish between region presence service and +	// region verification errors? +	mSharedData->onRegionVerificationFailed();  } - -LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(ResponsePtr data, const LLSD& content) : mSharedData(data), mContent(content) +LLRegionPresenceVerifier::VerifiedDestinationResponder::VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, const LLSD& content, +	S32 retry_count): +	mUri(uri), +	mSharedData(data), +	mContent(content), +	mRetryCount(retry_count)   {  } - - +//virtual +LLRegionPresenceVerifier::VerifiedDestinationResponder::~VerifiedDestinationResponder() +{ +}  void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD& content)  { @@ -76,13 +111,14 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::result(const LLSD&  	{  		mSharedData->onRegionVerified(mContent);  	} -	else if (mSharedData->shouldRetry()) +	else if (mRetryCount > 0)  	{  		retry();  	}  	else  	{ -		llwarns << "Could not correctly look up region from region presence service. Region: " << mSharedData->getRegionUri() << llendl; +		llwarns << "Simulator verification failed. Region: " << mUri << llendl; +		mSharedData->onRegionVerificationFailed();  	}  } @@ -90,13 +126,21 @@ void LLRegionPresenceVerifier::VerifiedDestinationResponder::retry()  {  	LLSD headers;  	headers["Cache-Control"] = "no-cache, max-age=0"; -	llinfos << "Requesting region information, get uncached for region " << mSharedData->getRegionUri() << llendl; -	mSharedData->decrementRetries(); -	mSharedData->getHttpClient().get(mSharedData->getRegionUri(), new RegionResponder(mSharedData), headers); +	llinfos << "Requesting region information, get uncached for region " +			<< mUri << llendl; +	--mRetryCount; +	mSharedData->getHttpClient().get(mUri, new RegionResponder(mUri, mSharedData, mRetryCount), headers);  }  void LLRegionPresenceVerifier::VerifiedDestinationResponder::error(U32 status, const std::string& reason)  { -	retry(); +	if(mRetryCount > 0) +	{ +		retry(); +	} +	else +	{ +		llwarns << "Failed to contact simulator for verification. Region: " << mUri << llendl; +		mSharedData->onRegionVerificationFailed(); +	}  } - diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h index d1de608ec6..f11eeef50c 100644 --- a/indra/llmessage/llregionpresenceverifier.h +++ b/indra/llmessage/llregionpresenceverifier.h @@ -1,5 +1,5 @@  /**  - * @file  + * @file llregionpresenceverifier.cpp   * @brief    *   * $LicenseInfo:firstyear=2008&license=viewergpl$ @@ -26,7 +26,7 @@  #include "llhttpclient.h"  #include <string>  #include "llsd.h" -#include <boost/shared_ptr.hpp> +#include <boost/intrusive_ptr.hpp>  class LLHTTPClientInterface; @@ -36,48 +36,57 @@ public:  	class Response  	{  	public: -		virtual ~Response() {} +		virtual ~Response() = 0;  		virtual bool checkValidity(const LLSD& content) const = 0;  		virtual void onRegionVerified(const LLSD& region_details) = 0; - -		virtual void decrementRetries() = 0; +		virtual void onRegionVerificationFailed() = 0;  		virtual LLHTTPClientInterface& getHttpClient() = 0; -		virtual std::string getRegionUri() const = 0; -		virtual bool shouldRetry() const = 0; -		virtual void onCompletedRegionRequest() {} +	public: /* but not really -- don't touch this */ +		U32 mReferenceCount;		  	}; -	typedef boost::shared_ptr<Response> ResponsePtr; +	typedef boost::intrusive_ptr<Response> ResponsePtr;  	class RegionResponder : public LLHTTPClient::Responder  	{  	public: -		RegionResponder(ResponsePtr data); +		RegionResponder(const std::string& uri, ResponsePtr data, +						S32 retry_count); +		virtual ~RegionResponder();   		virtual void result(const LLSD& content); -		virtual void completed( -			U32 status, -			const std::string& reason, -			const LLSD& content); +		virtual void error(U32 status, const std::string& reason);  	private:  		ResponsePtr mSharedData; +		std::string mUri; +		S32 mRetryCount;  	};  	class VerifiedDestinationResponder : public LLHTTPClient::Responder  	{  	public: -		VerifiedDestinationResponder(ResponsePtr data, const LLSD& content); +		VerifiedDestinationResponder(const std::string& uri, ResponsePtr data, +									 const LLSD& content, S32 retry_count); +		virtual ~VerifiedDestinationResponder();  		virtual void result(const LLSD& content);  		virtual void error(U32 status, const std::string& reason); +		  	private:  		void retry();  		ResponsePtr mSharedData;  		LLSD mContent; +		std::string mUri; +		S32 mRetryCount;  	};  }; +namespace boost +{ +	void intrusive_ptr_add_ref(LLRegionPresenceVerifier::Response* p); +	void intrusive_ptr_release(LLRegionPresenceVerifier::Response* p); +};  #endif //LL_LLREGIONPRESENCEVERIFIER_H diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp index 615eff405d..da6d1c84a8 100644 --- a/indra/llmessage/llstoredmessage.cpp +++ b/indra/llmessage/llstoredmessage.cpp @@ -1,5 +1,5 @@  /**  - * @file  + * @file llstoredmessage.cpp   * @brief    *   * $LicenseInfo:firstyear=2009&license=viewergpl$ diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h index e817f19bd2..6a27698b03 100644 --- a/indra/llmessage/llstoredmessage.h +++ b/indra/llmessage/llstoredmessage.h @@ -1,5 +1,5 @@  /**  - * @file  + * @file llstoredmessage.h   * @brief    *   * $LicenseInfo:firstyear=2009&license=viewergpl$ diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp index 70279a3c62..0872efba50 100644 --- a/indra/llmessage/llthrottle.cpp +++ b/indra/llmessage/llthrottle.cpp @@ -265,6 +265,31 @@ BOOL LLThrottleGroup::setNominalBPS(F32* throttle_vec)  	return changed;  } +// Return bits available in the channel +S32		LLThrottleGroup::getAvailable(S32 throttle_cat) +{ +	S32 retval = 0; + +	F32 category_bps = mCurrentBPS[throttle_cat]; +	F32 lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME; + +	// use a temporary bits_available +	// since we don't want to change mBitsAvailable every time +	F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]); +	F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time); + +	if (bits_available >= lookahead_bits) +	{ +		retval = (S32) gThrottleMaximumBPS[throttle_cat]; +	} +	else  +	{ +		retval = (S32) bits_available; +	} +	 +	return retval; +} +  BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)  { diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h index 7d1679beb2..47a7c653b2 100644 --- a/indra/llmessage/llthrottle.h +++ b/indra/llmessage/llthrottle.h @@ -84,6 +84,8 @@ public:  	BOOL	dynamicAdjust();		// Shift bandwidth from idle channels to busy channels, TRUE if adjustment occurred  	BOOL	setNominalBPS(F32* throttle_vec);				// TRUE if any value was different, resets adjustment system if was different +	S32		getAvailable(S32 throttle_cat);					// Return bits available in the channel +  	void packThrottle(LLDataPacker &dp) const;  	void unpackThrottle(LLDataPacker &dp);  public: diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 3ab8057abb..81b7761ed5 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -51,6 +51,7 @@ static const U32 HTTP_STATUS_PIPE_ERROR = 499;   * String constants   */  const std::string CONTEXT_DEST_URI_SD_LABEL("dest_uri"); +const std::string CONTEXT_TRANSFERED_BYTES("transfered_bytes");  static size_t headerCallback(void* data, size_t size, size_t nmemb, void* user); @@ -247,7 +248,29 @@ LLIOPipe::EStatus LLURLRequest::process_impl(  	PUMP_DEBUG;  	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);  	//llinfos << "LLURLRequest::process_impl()" << llendl; -	if(!buffer) return STATUS_ERROR; +	if (!buffer) return STATUS_ERROR; +	 +	// we're still waiting or prcessing, check how many +	// bytes we have accumulated. +	const S32 MIN_ACCUMULATION = 100000; +	if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION)) +	{ +		 // This is a pretty sloppy calculation, but this +		 // tries to make the gross assumption that if data +		 // is coming in at 56kb/s, then this transfer will +		 // probably succeed. So, if we're accumlated +		 // 100,000 bytes (MIN_ACCUMULATION) then let's +		 // give this client another 2s to complete. +		 const F32 TIMEOUT_ADJUSTMENT = 2.0f; +		 mDetail->mByteAccumulator = 0; +		 pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT); +		 lldebugs << "LLURLRequest adjustTimeoutSeconds for request: " << mDetail->mURL << llendl; +		 if (mState == STATE_INITIALIZED) +		 { +			  llinfos << "LLURLRequest adjustTimeoutSeconds called during upload" << llendl; +		 } +	} +  	switch(mState)  	{  	case STATE_INITIALIZED: @@ -286,27 +309,14 @@ LLIOPipe::EStatus LLURLRequest::process_impl(  			bool newmsg = mDetail->mCurlRequest->getResult(&result);  			if(!newmsg)  			{ -				// we're still waiting or prcessing, check how many -				// bytes we have accumulated. -				const S32 MIN_ACCUMULATION = 100000; -				if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION)) -				{ -					// This is a pretty sloppy calculation, but this -					// tries to make the gross assumption that if data -					// is coming in at 56kb/s, then this transfer will -					// probably succeed. So, if we're accumlated -					// 100,000 bytes (MIN_ACCUMULATION) then let's -					// give this client another 2s to complete. -					const F32 TIMEOUT_ADJUSTMENT = 2.0f; -					mDetail->mByteAccumulator = 0; -					pump->adjustTimeoutSeconds(TIMEOUT_ADJUSTMENT); -				} -  				// keep processing  				break;  			}  			mState = STATE_HAVE_RESPONSE; +			context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes; +			context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes; +			lldebugs << this << "Setting context to " << context << llendl;  			switch(result)  			{  				case CURLE_OK: @@ -353,10 +363,16 @@ LLIOPipe::EStatus LLURLRequest::process_impl(  		// we already stuffed everything into channel in in the curl  		// callback, so we are done.  		eos = true; +		context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes; +		context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes; +		lldebugs << this << "Setting context to " << context << llendl;  		return STATUS_DONE;  	default:  		PUMP_DEBUG; +		context[CONTEXT_REQUEST][CONTEXT_TRANSFERED_BYTES] = mRequestTransferedBytes; +		context[CONTEXT_RESPONSE][CONTEXT_TRANSFERED_BYTES] = mResponseTransferedBytes; +		lldebugs << this << "Setting context to " << context << llendl;  		return STATUS_ERROR;  	}  } @@ -369,6 +385,8 @@ void LLURLRequest::initialize()  	mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);  	mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);  	mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this); +	mRequestTransferedBytes = 0; +	mResponseTransferedBytes = 0;  }  bool LLURLRequest::configure() @@ -471,6 +489,7 @@ size_t LLURLRequest::downCallback(  		req->mDetail->mChannels.out(),  		(U8*)data,  		bytes); +	req->mResponseTransferedBytes += bytes;  	req->mDetail->mByteAccumulator += bytes;  	return bytes;  } @@ -494,6 +513,7 @@ size_t LLURLRequest::upCallback(  		req->mDetail->mLastRead,  		(U8*)data,  		bytes); +	req->mRequestTransferedBytes += bytes;  	return bytes;  } diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index 86ef71f085..cb3c466440 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -45,6 +45,12 @@  #include "llchainio.h"  #include "llerror.h" + +extern const std::string CONTEXT_REQUEST; +extern const std::string CONTEXT_DEST_URI_SD_LABEL; +extern const std::string CONTEXT_RESPONSE; +extern const std::string CONTEXT_TRANSFERED_BYTES; +  class LLURLRequestDetail;  class LLURLRequestComplete; @@ -208,6 +214,8 @@ protected:  	ERequestAction mAction;  	LLURLRequestDetail* mDetail;  	LLIOPipe::ptr_t mCompletionCallback; +	 S32 mRequestTransferedBytes; +	 S32 mResponseTransferedBytes;  private:  	/**  diff --git a/indra/llmessage/tests/llregionpresenceverifier_test.cpp b/indra/llmessage/tests/llregionpresenceverifier_test.cpp new file mode 100644 index 0000000000..b7602ef15c --- /dev/null +++ b/indra/llmessage/tests/llregionpresenceverifier_test.cpp @@ -0,0 +1,111 @@ +/**  + * @file  + * @brief  + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + *  + * Copyright (c) 2001-2008, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "../test/lltut.h" +#include "llregionpresenceverifier.h" +#include "llcurl_stub.cpp" +#include "llhost.cpp" +#include "net.cpp" +#include "lltesthttpclientadapter.cpp" + +class LLTestResponse : public LLRegionPresenceVerifier::Response +{ +public: + +	virtual bool checkValidity(const LLSD& content) const +	{ +		return true; +	} + +	virtual void onRegionVerified(const LLSD& region_details) +	{ +	} + +	virtual void onRegionVerificationFailed() +	{ +	} +	 +	virtual LLHTTPClientInterface& getHttpClient() +	{ +		return mHttpInterface; +	} + +	LLTestHTTPClientAdapter mHttpInterface; +}; + +namespace tut +{ +	struct LLRegionPresenceVerifierData +	{ +		LLRegionPresenceVerifierData() : +			mResponse(new LLTestResponse()), +			mResponder("", LLRegionPresenceVerifier::ResponsePtr(mResponse), +					   LLSD(), 3) +		{ +		} +		 +		LLTestResponse* mResponse; +		LLRegionPresenceVerifier::VerifiedDestinationResponder mResponder; +	}; + +	typedef test_group<LLRegionPresenceVerifierData> factory; +	typedef factory::object object; +} + +namespace +{ +	tut::factory tf("LLRegionPresenceVerifier test"); +} + +namespace tut +{ +	// Test that VerifiedDestinationResponder does retry +    // on error when shouldRetry returns true. +	template<> template<> +	void object::test<1>() +	{ +		mResponder.error(500, "Internal server error"); +		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 1); +	} + +	// Test that VerifiedDestinationResponder only retries +	// on error until shouldRetry returns false. +	template<> template<> +	void object::test<2>() +	{ +		mResponder.error(500, "Internal server error"); +		mResponder.error(500, "Internal server error"); +		mResponder.error(500, "Internal server error"); +		mResponder.error(500, "Internal server error"); +		ensure_equals(mResponse->mHttpInterface.mGetUrl.size(), 3); +	} +} + | 
