diff options
40 files changed, 1817 insertions, 1105 deletions
@@ -258,3 +258,4 @@ c6175c955a19e9b9353d242889ec1779b5762522 DRTVWR-105_3.2.5-release  c6175c955a19e9b9353d242889ec1779b5762522 3.2.5-release  3d75c836d178c7c7e788f256afe195f6cab764a2 DRTVWR-111_3.2.7-beta1  3d75c836d178c7c7e788f256afe195f6cab764a2 3.2.7-beta1 +89980333c99dbaf1787fe20784f1d8849e9b5d4f 3.2.8-start diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 4063cc730b..a6ad6b125c 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -337,11 +337,7 @@ LLMutex::~LLMutex()  void LLMutex::lock()  { -#if LL_DARWIN -	if (mLockingThread == LLThread::currentID()) -#else -	if (mLockingThread == sThreadID) -#endif +	if(isSelfLocked())  	{ //redundant lock  		mCount++;  		return; @@ -398,6 +394,15 @@ bool LLMutex::isLocked()  	}  } +bool LLMutex::isSelfLocked() +{ +#if LL_DARWIN +	return mLockingThread == LLThread::currentID(); +#else +	return mLockingThread == sThreadID; +#endif +} +  U32 LLMutex::lockingThread() const  {  	return mLockingThread; diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index f0e0de6173..b52e70ab2e 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -151,6 +151,7 @@ public:  	void lock();		// blocks  	void unlock();  	bool isLocked(); 	// non-blocking, but does do a lock/unlock so not free +	bool isSelfLocked(); //return true if locked in a same thread  	U32 lockingThread() const; //get ID of locking thread  protected: diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 99ab053b25..27cdfcaa4e 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@  const S32 LL_VERSION_MAJOR = 3;  const S32 LL_VERSION_MINOR = 2; -const S32 LL_VERSION_PATCH = 8; +const S32 LL_VERSION_PATCH = 9;  const S32 LL_VERSION_BUILD = 0;  const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llmessage/llbuffer.cpp b/indra/llmessage/llbuffer.cpp index 0316797f00..250cace6e9 100644 --- a/indra/llmessage/llbuffer.cpp +++ b/indra/llmessage/llbuffer.cpp @@ -32,6 +32,9 @@  #include "llmath.h"  #include "llmemtype.h"  #include "llstl.h" +#include "llthread.h" + +#define ASSERT_LLBUFFERARRAY_MUTEX_LOCKED llassert(!mMutexp || mMutexp->isSelfLocked());  /**    * LLSegment @@ -224,7 +227,8 @@ void LLHeapBuffer::allocate(S32 size)   * LLBufferArray   */  LLBufferArray::LLBufferArray() : -	mNextBaseChannel(0) +	mNextBaseChannel(0), +	mMutexp(NULL)  {  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  } @@ -233,6 +237,8 @@ LLBufferArray::~LLBufferArray()  {  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	std::for_each(mBuffers.begin(), mBuffers.end(), DeletePointer()); + +	delete mMutexp;  }  // static @@ -243,14 +249,57 @@ LLChannelDescriptors LLBufferArray::makeChannelConsumer(  	return rv;  } +void LLBufferArray::lock() +{ +	if(mMutexp) +	{ +		mMutexp->lock() ; +	} +} + +void LLBufferArray::unlock() +{ +	if(mMutexp) +	{ +		mMutexp->unlock() ; +	} +} + +LLMutex* LLBufferArray::getMutex() +{ +	return mMutexp ; +} + +void LLBufferArray::setThreaded(bool threaded) +{ +	if(threaded) +	{ +		if(!mMutexp) +		{ +			mMutexp = new LLMutex(NULL); +		} +	} +	else +	{ +		if(mMutexp) +		{ +			delete mMutexp ; +			mMutexp = NULL ; +		} +	} +} +  LLChannelDescriptors LLBufferArray::nextChannel()  {  	LLChannelDescriptors rv(mNextBaseChannel++);  	return rv;  } +//mMutexp should be locked before calling this.  S32 LLBufferArray::capacity() const  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED +  	S32 total = 0;  	const_buffer_iterator_t iter = mBuffers.begin();  	const_buffer_iterator_t end = mBuffers.end(); @@ -263,6 +312,8 @@ S32 LLBufferArray::capacity() const  bool LLBufferArray::append(S32 channel, const U8* src, S32 len)  { +	LLMutexLock lock(mMutexp) ; +  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	std::vector<LLSegment> segments;  	if(copyIntoBuffers(channel, src, len, segments)) @@ -273,8 +324,11 @@ bool LLBufferArray::append(S32 channel, const U8* src, S32 len)  	return false;  } +//mMutexp should be locked before calling this.  bool LLBufferArray::prepend(S32 channel, const U8* src, S32 len)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED +  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	std::vector<LLSegment> segments;  	if(copyIntoBuffers(channel, src, len, segments)) @@ -293,6 +347,8 @@ bool LLBufferArray::insertAfter(  {  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	std::vector<LLSegment> segments; + +	LLMutexLock lock(mMutexp) ;  	if(mSegments.end() != segment)  	{  		++segment; @@ -305,8 +361,11 @@ bool LLBufferArray::insertAfter(  	return false;  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED +  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	segment_iterator_t end = mSegments.end();  	segment_iterator_t it = getSegment(address); @@ -335,20 +394,26 @@ LLBufferArray::segment_iterator_t LLBufferArray::splitAfter(U8* address)  	return rv;  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::beginSegment()  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	return mSegments.begin();  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::endSegment()  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	return mSegments.end();  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(  	U8* address,  	LLSegment& segment)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	segment_iterator_t rv = mSegments.begin();  	segment_iterator_t end = mSegments.end(); @@ -395,8 +460,10 @@ LLBufferArray::segment_iterator_t LLBufferArray::constructSegmentAfter(  	return rv;  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	segment_iterator_t end = mSegments.end();  	if(!address)  	{ @@ -414,9 +481,11 @@ LLBufferArray::segment_iterator_t LLBufferArray::getSegment(U8* address)  	return end;  } +//mMutexp should be locked before calling this.  LLBufferArray::const_segment_iterator_t LLBufferArray::getSegment(  	U8* address) const  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	const_segment_iterator_t end = mSegments.end();  	if(!address)  	{ @@ -466,6 +535,8 @@ S32 LLBufferArray::countAfter(S32 channel, U8* start) const  	S32 count = 0;  	S32 offset = 0;  	const_segment_iterator_t it; + +	LLMutexLock lock(mMutexp) ;  	const_segment_iterator_t end = mSegments.end();  	if(start)  	{ @@ -517,6 +588,8 @@ U8* LLBufferArray::readAfter(  	len = 0;  	S32 bytes_to_copy = 0;  	const_segment_iterator_t it; + +	LLMutexLock lock(mMutexp) ;  	const_segment_iterator_t end = mSegments.end();  	if(start)  	{ @@ -568,6 +641,7 @@ U8* LLBufferArray::seek(  	U8* start,  	S32 delta) const  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	const_segment_iterator_t it;  	const_segment_iterator_t end = mSegments.end(); @@ -709,9 +783,14 @@ U8* LLBufferArray::seek(  	return rv;  } +//test use only  bool LLBufferArray::takeContents(LLBufferArray& source)  {  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER); + +	LLMutexLock lock(mMutexp); +	source.lock(); +  	std::copy(  		source.mBuffers.begin(),  		source.mBuffers.end(), @@ -723,13 +802,17 @@ bool LLBufferArray::takeContents(LLBufferArray& source)  		std::back_insert_iterator<segment_list_t>(mSegments));  	source.mSegments.clear();  	source.mNextBaseChannel = 0; +	source.unlock(); +  	return true;  } +//mMutexp should be locked before calling this.  LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(  	S32 channel,  	S32 len)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	// start at the end of the buffers, because it is the most likely  	// to have free space. @@ -765,8 +848,10 @@ LLBufferArray::segment_iterator_t LLBufferArray::makeSegment(  	return send;  } +//mMutexp should be locked before calling this.  bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	// Find out which buffer contains the segment, and if it is found, @@ -792,13 +877,14 @@ bool LLBufferArray::eraseSegment(const segment_iterator_t& erase_iter)  	return rv;  } - +//mMutexp should be locked before calling this.  bool LLBufferArray::copyIntoBuffers(  	S32 channel,  	const U8* src,  	S32 len,  	std::vector<LLSegment>& segments)  { +	ASSERT_LLBUFFERARRAY_MUTEX_LOCKED  	LLMemType m1(LLMemType::MTYPE_IO_BUFFER);  	if(!src || !len) return false;  	S32 copied = 0; diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h index 1c42b6fbc6..ccdb9fa7ee 100644 --- a/indra/llmessage/llbuffer.h +++ b/indra/llmessage/llbuffer.h @@ -39,6 +39,7 @@  #include <list>  #include <vector> +class LLMutex;  /**    * @class LLChannelDescriptors   * @brief A way simple interface to accesss channels inside a buffer @@ -564,6 +565,29 @@ public:  	 * @return Returns true on success.  	 */  	bool eraseSegment(const segment_iterator_t& iter); + +	/** +	* @brief Lock the mutex if it exists +	* This method locks mMutexp to make accessing LLBufferArray thread-safe +	*/ +	void lock(); + +	/** +	* @brief Unlock the mutex if it exists +	*/ +	void unlock(); + +	/** +	* @brief Return mMutexp +	*/ +	LLMutex* getMutex(); + +	/** +	* @brief Set LLBufferArray to be shared across threads or not +	* This method is to create mMutexp if is threaded. +	* @param threaded Indicates this LLBufferArray instance is shared across threads if true. +	*/ +	void setThreaded(bool threaded);  	//@}  protected: @@ -595,6 +619,7 @@ protected:  	S32 mNextBaseChannel;  	buffer_list_t mBuffers;  	segment_list_t mSegments; +	LLMutex* mMutexp;  };  #endif // LL_LLBUFFER_H diff --git a/indra/llmessage/llbufferstream.cpp b/indra/llmessage/llbufferstream.cpp index 6257983c43..8d8ad05ad5 100644 --- a/indra/llmessage/llbufferstream.cpp +++ b/indra/llmessage/llbufferstream.cpp @@ -31,6 +31,7 @@  #include "llbuffer.h"  #include "llmemtype.h" +#include "llthread.h"  static const S32 DEFAULT_OUTPUT_SEGMENT_SIZE = 1024 * 4; @@ -62,6 +63,7 @@ int LLBufferStreamBuf::underflow()  		return EOF;  	} +	LLMutexLock lock(mBuffer->getMutex());  	LLBufferArray::segment_iterator_t iter;  	LLBufferArray::segment_iterator_t end = mBuffer->endSegment();  	U8* last_pos = (U8*)gptr(); @@ -149,6 +151,7 @@ int LLBufferStreamBuf::overflow(int c)  	// since we got here, we have a buffer, and we have a character to  	// put on it.  	LLBufferArray::segment_iterator_t it; +	LLMutexLock lock(mBuffer->getMutex());  	it = mBuffer->makeSegment(mChannels.out(), DEFAULT_OUTPUT_SEGMENT_SIZE);  	if(it != mBuffer->endSegment())  	{ @@ -210,6 +213,7 @@ int LLBufferStreamBuf::sync()  	// *NOTE: I bet we could just --address if address is not NULL.  	// Need to think about that. +	LLMutexLock lock(mBuffer->getMutex());  	address = mBuffer->seek(mChannels.out(), address, -1);  	if(address)  	{ @@ -273,6 +277,8 @@ streampos LLBufferStreamBuf::seekoff(  			// NULL is fine  			break;  		} + +		LLMutexLock lock(mBuffer->getMutex());  		address = mBuffer->seek(mChannels.in(), base_addr, off);  		if(address)  		{ @@ -304,6 +310,8 @@ streampos LLBufferStreamBuf::seekoff(  			// NULL is fine  			break;  		} + +		LLMutexLock lock(mBuffer->getMutex());  		address = mBuffer->seek(mChannels.out(), base_addr, off);  		if(address)  		{ diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index e17380fdf5..3bcaffc275 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -72,10 +72,9 @@  static const U32 EASY_HANDLE_POOL_SIZE		= 5;  static const S32 MULTI_PERFORM_CALL_REPEAT	= 5; -static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds +static const S32 CURL_REQUEST_TIMEOUT = 30; // seconds per operation  static const S32 MAX_ACTIVE_REQUEST_COUNT = 100; -static   // DEBUG //  S32 gCurlEasyCount = 0;  S32 gCurlMultiCount = 0; @@ -87,6 +86,11 @@ std::vector<LLMutex*> LLCurl::sSSLMutex;  std::string LLCurl::sCAPath;  std::string LLCurl::sCAFile;  LLCurlThread* LLCurl::sCurlThread = NULL ; +LLMutex* LLCurl::sHandleMutexp = NULL ; +S32      LLCurl::sTotalHandles = 0 ; +bool     LLCurl::sNotQuitting = true; +F32      LLCurl::sCurlRequestTimeOut = 120.f; //seonds +S32      LLCurl::sMaxHandles = 256; //max number of handles, (multi handles and easy handles combined).  void check_curl_code(CURLcode code)  { @@ -224,13 +228,15 @@ LLMutex* LLCurl::Easy::sHandleMutexp = NULL ;  //static  CURL* LLCurl::Easy::allocEasyHandle()  { +	llassert(LLCurl::getCurlThread()) ; +  	CURL* ret = NULL;  	LLMutexLock lock(sHandleMutexp) ;  	if (sFreeHandles.empty())  	{ -		ret = curl_easy_init(); +		ret = LLCurl::newEasyHandle();  	}  	else  	{ @@ -250,16 +256,27 @@ CURL* LLCurl::Easy::allocEasyHandle()  //static  void LLCurl::Easy::releaseEasyHandle(CURL* handle)  { +	static const S32 MAX_NUM_FREE_HANDLES = 32 ; +  	if (!handle)  	{ -		llerrs << "handle cannot be NULL!" << llendl; +		return ; //handle allocation failed. +		//llerrs << "handle cannot be NULL!" << llendl;  	}  	LLMutexLock lock(sHandleMutexp) ;  	if (sActiveHandles.find(handle) != sActiveHandles.end())  	{  		sActiveHandles.erase(handle); -		sFreeHandles.insert(handle); + +		if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES) +		{ +			sFreeHandles.insert(handle); +		} +		else +		{ +			LLCurl::deleteEasyHandle(handle) ; +		}  	}  	else  	{ @@ -302,6 +319,14 @@ LLCurl::Easy::~Easy()  	--gCurlEasyCount;  	curl_slist_free_all(mHeaders);  	for_each(mStrings.begin(), mStrings.end(), DeletePointerArray()); + +	if (mResponder && LLCurl::sNotQuitting) //aborted +	{	 +		std::string reason("Request timeout, aborted.") ; +		mResponder->completedRaw(408, //HTTP_REQUEST_TIME_OUT, timeout, abort +			reason, mChannels, mOutput);		 +	} +	mResponder = NULL;  }  void LLCurl::Easy::resetState() @@ -474,6 +499,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,  	LLProxy::getInstance()->applyProxySettings(this);  	mOutput.reset(new LLBufferArray); +	mOutput->setThreaded(true);  	setopt(CURLOPT_WRITEFUNCTION, (void*)&curlWriteCallback);  	setopt(CURLOPT_WRITEDATA, (void*)this); @@ -517,8 +543,7 @@ void LLCurl::Easy::prepRequest(const std::string& url,  }  //////////////////////////////////////////////////////////////////////////// -LLMutex* LLCurl::Multi::sMultiInitMutexp = NULL ; -LLCurl::Multi::Multi() +LLCurl::Multi::Multi(F32 idle_time_out)  	: mQueued(0),  	  mErrorCount(0),  	  mState(STATE_READY), @@ -527,28 +552,47 @@ LLCurl::Multi::Multi()  	  mDeletionMutexp(NULL),  	  mEasyMutexp(NULL)  { -	mCurlMultiHandle = initMulti(); +	mCurlMultiHandle = LLCurl::newMultiHandle();  	if (!mCurlMultiHandle)  	{  		llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; -		mCurlMultiHandle = initMulti(); +		mCurlMultiHandle = LLCurl::newMultiHandle();  	} -	llassert_always(mCurlMultiHandle);	 - -	if(LLCurl::getCurlThread()->getThreaded()) +	//llassert_always(mCurlMultiHandle);	 +	 +	if(mCurlMultiHandle)  	{ -		mMutexp = new LLMutex(NULL) ; -		mDeletionMutexp = new LLMutex(NULL) ; -		mEasyMutexp = new LLMutex(NULL) ; -	} -	LLCurl::getCurlThread()->addMulti(this) ; +		if(LLCurl::getCurlThread()->getThreaded()) +		{ +			mMutexp = new LLMutex(NULL) ; +			mDeletionMutexp = new LLMutex(NULL) ; +			mEasyMutexp = new LLMutex(NULL) ; +		} +		LLCurl::getCurlThread()->addMulti(this) ; -	++gCurlMultiCount; +		mIdleTimeOut = idle_time_out ; +		if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut) +		{ +			mIdleTimeOut = LLCurl::sCurlRequestTimeOut ; +		} + +		++gCurlMultiCount; +	}  }  LLCurl::Multi::~Multi()  { +	cleanup() ;	 +} + +void LLCurl::Multi::cleanup() +{ +	if(!mCurlMultiHandle) +	{ +		return ; //nothing to clean. +	} +  	// Clean up active  	for(easy_active_list_t::iterator iter = mEasyActiveList.begin();  		iter != mEasyActiveList.end(); ++iter) @@ -564,7 +608,8 @@ LLCurl::Multi::~Multi()  	for_each(mEasyFreeList.begin(), mEasyFreeList.end(), DeletePointer());	  	mEasyFreeList.clear(); -	check_curl_multi_code(curl_multi_cleanup(mCurlMultiHandle)); +	check_curl_multi_code(LLCurl::deleteMultiHandle(mCurlMultiHandle)); +	mCurlMultiHandle = NULL ;  	delete mMutexp ;  	mMutexp = NULL ; @@ -572,15 +617,13 @@ LLCurl::Multi::~Multi()  	mDeletionMutexp = NULL ;  	delete mEasyMutexp ;  	mEasyMutexp = NULL ; - +	 +	mQueued = 0 ; +	mState = STATE_COMPLETED; +	  	--gCurlMultiCount; -} - -CURLM* LLCurl::Multi::initMulti() -{ -	LLMutexLock lock(sMultiInitMutexp) ; -	return curl_multi_init() ; +	return ;  }  void LLCurl::Multi::lock() @@ -604,6 +647,7 @@ void LLCurl::Multi::markDead()  	LLMutexLock lock(mDeletionMutexp) ;  	mDead = TRUE ; +	LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ;   }  void LLCurl::Multi::setState(LLCurl::Multi::ePerformState state) @@ -630,6 +674,11 @@ bool LLCurl::Multi::isCompleted()  bool LLCurl::Multi::waitToComplete()  { +	if(!isValid()) +	{ +		return true ; +	} +  	if(!mMutexp) //not threaded  	{  		doPerform() ; @@ -639,7 +688,7 @@ bool LLCurl::Multi::waitToComplete()  	bool completed = (STATE_COMPLETED == mState) ;  	if(!completed)  	{ -		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_URGENT) ; +		LLCurl::getCurlThread()->setPriority(mHandle, LLQueuedThread::PRIORITY_HIGH) ;  	}  	return completed; @@ -689,7 +738,12 @@ bool LLCurl::Multi::doPerform()  		}  		mQueued = q;	 -		setState(STATE_COMPLETED) ; +		setState(STATE_COMPLETED) ;		 +		mIdleTimer.reset() ; +	} +	else if(mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it. +	{ +		dead = true ;  	}  	return dead ; @@ -697,6 +751,11 @@ bool LLCurl::Multi::doPerform()  S32 LLCurl::Multi::process()  { +	if(!isValid()) +	{ +		return 0 ; +	} +  	waitToComplete() ;  	if (getState() != STATE_COMPLETED) @@ -849,7 +908,11 @@ bool LLCurlThread::CurlRequest::processRequest()  	if(mMulti)  	{  		completed = mCurlThread->doMultiPerform(mMulti) ; -		setPriority(LLQueuedThread::PRIORITY_LOW) ; + +		if(!completed) +		{ +			setPriority(LLQueuedThread::PRIORITY_LOW) ; +		}  	}  	return completed ; @@ -857,24 +920,26 @@ bool LLCurlThread::CurlRequest::processRequest()  void LLCurlThread::CurlRequest::finishRequest(bool completed)  { -	mCurlThread->deleteMulti(mMulti) ; +	if(mMulti->isDead()) +	{ +		mCurlThread->deleteMulti(mMulti) ; +	} +	else +	{ +		mCurlThread->cleanupMulti(mMulti) ; //being idle too long, remove the request. +	} +  	mMulti = NULL ;  }  LLCurlThread::LLCurlThread(bool threaded) :  	LLQueuedThread("curlthread", threaded)  { -	if(!LLCurl::Multi::sMultiInitMutexp) -	{ -		LLCurl::Multi::sMultiInitMutexp = new LLMutex(NULL) ; -	}  }  //virtual   LLCurlThread::~LLCurlThread()   { -	delete LLCurl::Multi::sMultiInitMutexp ; -	LLCurl::Multi::sMultiInitMutexp = NULL ;  }  S32 LLCurlThread::update(F32 max_time_ms) @@ -896,7 +961,19 @@ void LLCurlThread::addMulti(LLCurl::Multi* multi)  void LLCurlThread::killMulti(LLCurl::Multi* multi)  { -	multi->markDead() ; +	if(!multi) +	{ +		return ; +	} + +	if(multi->isValid()) +	{ +		multi->markDead() ; +	} +	else +	{ +		deleteMulti(multi) ; +	}  }  //private @@ -910,6 +987,13 @@ void LLCurlThread::deleteMulti(LLCurl::Multi* multi)  {  	delete multi ;  } + +//private +void LLCurlThread::cleanupMulti(LLCurl::Multi* multi)  +{ +	multi->cleanup() ; +} +  //------------------------------------------------------------  //static @@ -942,7 +1026,14 @@ LLCurlRequest::~LLCurlRequest()  void LLCurlRequest::addMulti()  {  	LLCurl::Multi* multi = new LLCurl::Multi(); -	 +	if(!multi->isValid()) +	{ +		LLCurl::getCurlThread()->killMulti(multi) ; +		mActiveMulti = NULL ; +		mActiveRequestCount = 0 ; +		return; +	} +  	mMultiSet.insert(multi);  	mActiveMulti = multi;  	mActiveRequestCount = 0; @@ -956,7 +1047,12 @@ LLCurl::Easy* LLCurlRequest::allocEasy()  	{  		addMulti();  	} -	llassert_always(mActiveMulti); +	if(!mActiveMulti) +	{ +		return NULL ; +	} + +	//llassert_always(mActiveMulti);  	++mActiveRequestCount;  	LLCurl::Easy* easy = mActiveMulti->allocEasy();  	return easy; @@ -1066,6 +1162,19 @@ S32 LLCurlRequest::process()  	{  		curlmulti_set_t::iterator curiter = iter++;  		LLCurl::Multi* multi = *curiter; + +		if(!multi->isValid()) +		{ +			if(multi == mActiveMulti) +			{				 +				mActiveMulti = NULL ; +				mActiveRequestCount = 0 ; +			} +			mMultiSet.erase(curiter) ; +			LLCurl::getCurlThread()->killMulti(multi) ; +			continue ; +		} +  		S32 tres = multi->process();  		res += tres;  		if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0) @@ -1086,6 +1195,19 @@ S32 LLCurlRequest::getQueued()  	{  		curlmulti_set_t::iterator curiter = iter++;  		LLCurl::Multi* multi = *curiter; +		 +		if(!multi->isValid()) +		{ +			if(multi == mActiveMulti) +			{				 +				mActiveMulti = NULL ; +				mActiveRequestCount = 0 ; +			} +			LLCurl::getCurlThread()->killMulti(multi); +			mMultiSet.erase(curiter) ; +			continue ; +		} +  		queued += multi->mQueued;  		if (multi->getState() != LLCurl::Multi::STATE_READY)  		{ @@ -1105,13 +1227,22 @@ LLCurlEasyRequest::LLCurlEasyRequest()  {  	mMulti = new LLCurl::Multi(); -	mEasy = mMulti->allocEasy(); -	if (mEasy) +	if(mMulti->isValid())  	{ -		mEasy->setErrorBuffer(); -		mEasy->setCA(); -		// Set proxy settings if configured to do so. -		LLProxy::getInstance()->applyProxySettings(mEasy); +		mEasy = mMulti->allocEasy(); +		if (mEasy) +		{ +			mEasy->setErrorBuffer(); +			mEasy->setCA(); +			// Set proxy settings if configured to do so. +			LLProxy::getInstance()->applyProxySettings(mEasy); +		} +	} +	else +	{ +		LLCurl::getCurlThread()->killMulti(mMulti) ; +		mEasy = NULL ; +		mMulti = NULL ;  	}  } @@ -1122,7 +1253,7 @@ LLCurlEasyRequest::~LLCurlEasyRequest()  void LLCurlEasyRequest::setopt(CURLoption option, S32 value)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(option, value);  	} @@ -1130,7 +1261,7 @@ void LLCurlEasyRequest::setopt(CURLoption option, S32 value)  void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setoptString(option, value);  	} @@ -1138,7 +1269,7 @@ void LLCurlEasyRequest::setoptString(CURLoption option, const std::string& value  void LLCurlEasyRequest::setPost(char* postdata, S32 size)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(CURLOPT_POST, 1);  		mEasy->setopt(CURLOPT_POSTFIELDS, postdata); @@ -1148,7 +1279,7 @@ void LLCurlEasyRequest::setPost(char* postdata, S32 size)  void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* userdata)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(CURLOPT_HEADERFUNCTION, (void*)callback);  		mEasy->setopt(CURLOPT_HEADERDATA, userdata); // aka CURLOPT_WRITEHEADER @@ -1157,7 +1288,7 @@ void LLCurlEasyRequest::setHeaderCallback(curl_header_callback callback, void* u  void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* userdata)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(CURLOPT_WRITEFUNCTION, (void*)callback);  		mEasy->setopt(CURLOPT_WRITEDATA, userdata); @@ -1166,7 +1297,7 @@ void LLCurlEasyRequest::setWriteCallback(curl_write_callback callback, void* use  void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userdata)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(CURLOPT_READFUNCTION, (void*)callback);  		mEasy->setopt(CURLOPT_READDATA, userdata); @@ -1175,7 +1306,7 @@ void LLCurlEasyRequest::setReadCallback(curl_read_callback callback, void* userd  void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void* userdata)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setopt(CURLOPT_SSL_CTX_FUNCTION, (void*)callback);  		mEasy->setopt(CURLOPT_SSL_CTX_DATA, userdata); @@ -1184,7 +1315,7 @@ void LLCurlEasyRequest::setSSLCtxCallback(curl_ssl_ctx_callback callback, void*  void LLCurlEasyRequest::slist_append(const char* str)  { -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->slist_append(str);  	} @@ -1195,7 +1326,7 @@ void LLCurlEasyRequest::sendRequest(const std::string& url)  	llassert_always(!mRequestSent);  	mRequestSent = true;  	lldebugs << url << llendl; -	if (mEasy) +	if (isValid() && mEasy)  	{  		mEasy->setHeaders();  		mEasy->setoptString(CURLOPT_URL, url); @@ -1207,7 +1338,7 @@ void LLCurlEasyRequest::requestComplete()  {  	llassert_always(mRequestSent);  	mRequestSent = false; -	if (mEasy) +	if (isValid() && mEasy)  	{  		mMulti->removeEasy(mEasy);  	} @@ -1216,6 +1347,10 @@ void LLCurlEasyRequest::requestComplete()  // Usage: Call getRestult until it returns false (no more messages)  bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info)  { +	if(!isValid()) +	{ +		return false ; +	}  	if (!mMulti->isCompleted())  	{ //we're busy, try again later  		return false; @@ -1280,7 +1415,7 @@ CURLMsg* LLCurlEasyRequest::info_read(S32* q, LLCurl::TransferInfo* info)  std::string LLCurlEasyRequest::getErrorString()  { -	return mEasy ? std::string(mEasy->getErrorBuffer()) : std::string(); +	return isValid() &&  mEasy ? std::string(mEasy->getErrorBuffer()) : std::string();  }  //////////////////////////////////////////////////////////////////////////// @@ -1306,8 +1441,11 @@ unsigned long LLCurl::ssl_thread_id(void)  }  #endif -void LLCurl::initClass(bool multi_threaded) +void LLCurl::initClass(F32 curl_reuest_timeout, S32 max_number_handles, bool multi_threaded)  { +	sCurlRequestTimeOut = curl_reuest_timeout ; //seconds +	sMaxHandles = max_number_handles ; //max number of handles, (multi handles and easy handles combined). +  	// Do not change this "unless you are familiar with and mean to control   	// internal operations of libcurl"  	// - http://curl.haxx.se/libcurl/c/curl_global_init.html @@ -1328,12 +1466,15 @@ void LLCurl::initClass(bool multi_threaded)  	sCurlThread = new LLCurlThread(multi_threaded) ;  	if(multi_threaded)  	{ +		sHandleMutexp = new LLMutex(NULL) ;  		Easy::sHandleMutexp = new LLMutex(NULL) ;  	}  }  void LLCurl::cleanupClass()  { +	sNotQuitting = false; //set quitting +  	//shut down curl thread  	while(1)  	{ @@ -1354,7 +1495,7 @@ void LLCurl::cleanupClass()  	for (std::set<CURL*>::iterator iter = Easy::sFreeHandles.begin(); iter != Easy::sFreeHandles.end(); ++iter)  	{  		CURL* curl = *iter; -		curl_easy_cleanup(curl); +		LLCurl::deleteEasyHandle(curl);  	}  	Easy::sFreeHandles.clear(); @@ -1362,9 +1503,77 @@ void LLCurl::cleanupClass()  	delete Easy::sHandleMutexp ;  	Easy::sHandleMutexp = NULL ; +	delete sHandleMutexp ; +	sHandleMutexp = NULL ; +  	llassert(Easy::sActiveHandles.empty());  } +//static  +CURLM* LLCurl::newMultiHandle() +{ +	LLMutexLock lock(sHandleMutexp) ; + +	if(sTotalHandles + 1 > sMaxHandles) +	{ +		llwarns << "no more handles available." << llendl ; +		return NULL ; //failed +	} +	sTotalHandles++; + +	CURLM* ret = curl_multi_init() ; +	if(!ret) +	{ +		llwarns << "curl_multi_init failed." << llendl ; +	} + +	return ret ; +} + +//static  +CURLMcode  LLCurl::deleteMultiHandle(CURLM* handle) +{ +	if(handle) +	{ +		LLMutexLock lock(sHandleMutexp) ;		 +		sTotalHandles-- ; +		return curl_multi_cleanup(handle) ; +	} +	return CURLM_OK ; +} + +//static  +CURL*  LLCurl::newEasyHandle() +{ +	LLMutexLock lock(sHandleMutexp) ; + +	if(sTotalHandles + 1 > sMaxHandles) +	{ +		llwarns << "no more handles available." << llendl ; +		return NULL ; //failed +	} +	sTotalHandles++; + +	CURL* ret = curl_easy_init() ; +	if(!ret) +	{ +		llwarns << "curl_easy_init failed." << llendl ; +	} + +	return ret ; +} + +//static  +void  LLCurl::deleteEasyHandle(CURL* handle) +{ +	if(handle) +	{ +		LLMutexLock lock(sHandleMutexp) ; +		curl_easy_cleanup(handle) ; +		sTotalHandles-- ; +	} +} +  const unsigned int LLCurl::MAX_REDIRECTS = 5;  // Provide access to LLCurl free functions outside of llcurl.cpp without polluting the global namespace. diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 9c2c215c7a..fd664c0fa1 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -43,6 +43,7 @@  #include "llsd.h"  #include "llthread.h"  #include "llqueuedthread.h" +#include "llframetimer.h"  class LLMutex;  class LLCurlThread; @@ -162,7 +163,7 @@ public:  	/**  	 * @ brief Initialize LLCurl class  	 */ -	static void initClass(bool multi_threaded = false); +	static void initClass(F32 curl_reuest_timeout = 120.f, S32 max_number_handles = 256, bool multi_threaded = false);  	/**  	 * @ brief Cleanup LLCurl class @@ -182,11 +183,24 @@ public:  	static unsigned long ssl_thread_id(void);  	static LLCurlThread* getCurlThread() { return sCurlThread ;} + +	static CURLM* newMultiHandle() ; +	static CURLMcode deleteMultiHandle(CURLM* handle) ; +	static CURL*  newEasyHandle() ; +	static void   deleteEasyHandle(CURL* handle) ; +  private:  	static std::string sCAPath;  	static std::string sCAFile;  	static const unsigned int MAX_REDIRECTS;  	static LLCurlThread* sCurlThread; + +	static LLMutex* sHandleMutexp ; +	static S32      sTotalHandles ; +	static S32      sMaxHandles; +public: +	static bool     sNotQuitting; +	static F32      sCurlRequestTimeOut;	  };  class LLCurl::Easy @@ -277,7 +291,7 @@ public:  		STATE_COMPLETED=2  	} ePerformState; -	Multi();	 +	Multi(F32 idle_time_out = 0.f);	  	LLCurl::Easy* allocEasy();  	bool addEasy(LLCurl::Easy* easy);	 @@ -288,7 +302,10 @@ public:  	void setState(ePerformState state) ;  	ePerformState getState() ; +	  	bool isCompleted() ; +	bool isValid() {return mCurlMultiHandle != NULL ;} +	bool isDead() {return mDead;}  	bool waitToComplete() ; @@ -299,9 +316,9 @@ public:  	S32 mQueued;  	S32 mErrorCount; -	static CURLM* initMulti() ;  private:  	void easyFree(LLCurl::Easy*); +	void cleanup() ;  	CURLM* mCurlMultiHandle; @@ -319,8 +336,8 @@ private:  	LLMutex* mMutexp ;  	LLMutex* mDeletionMutexp ;  	LLMutex* mEasyMutexp ; - -	static LLMutex* sMultiInitMutexp ; +	LLFrameTimer mIdleTimer ; +	F32 mIdleTimeOut;  };  class LLCurlThread : public LLQueuedThread @@ -357,6 +374,7 @@ public:  private:  	bool doMultiPerform(LLCurl::Multi* multi) ;  	void deleteMulti(LLCurl::Multi* multi) ; +	void cleanupMulti(LLCurl::Multi* multi) ;  } ;  namespace boost @@ -414,6 +432,7 @@ public:  	std::string getErrorString();  	bool isCompleted() {return mMulti->isCompleted() ;}  	bool wait() { return mMulti->waitToComplete(); } +	bool isValid() {return mMulti && mMulti->isValid(); }  	LLCurl::Easy* getEasy() const { return mEasy; } diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp index 2bca517e97..612d765969 100644 --- a/indra/llmessage/llhttpassetstorage.cpp +++ b/indra/llmessage/llhttpassetstorage.cpp @@ -232,7 +232,8 @@ LLSD LLHTTPAssetRequest::getFullDetails() const  void LLHTTPAssetRequest::setupCurlHandle()  {  	// *NOTE: Similar code exists in mapserver/llcurlutil.cpp  JC -	mCurlHandle = curl_easy_init(); +	mCurlHandle = LLCurl::newEasyHandle(); +	llassert_always(mCurlHandle != NULL) ;  	// Apply proxy settings if configured to do so  	LLProxy::getInstance()->applyProxySettings(mCurlHandle); @@ -278,7 +279,7 @@ void LLHTTPAssetRequest::setupCurlHandle()  void LLHTTPAssetRequest::cleanupCurlHandle()  { -	curl_easy_cleanup(mCurlHandle); +	LLCurl::deleteEasyHandle(mCurlHandle);  	if (mAssetStoragep)  	{  		// Terminating a request.  Thus upload or download is no longer pending. @@ -429,12 +430,13 @@ void LLHTTPAssetStorage::_init(const std::string& web_host, const std::string& l  	// curl_global_init moved to LLCurl::initClass() -	mCurlMultiHandle = curl_multi_init(); +	mCurlMultiHandle = LLCurl::newMultiHandle() ; +	llassert_always(mCurlMultiHandle != NULL) ;  }  LLHTTPAssetStorage::~LLHTTPAssetStorage()  { -	curl_multi_cleanup(mCurlMultiHandle); +	LLCurl::deleteMultiHandle(mCurlMultiHandle);  	mCurlMultiHandle = NULL;  	// curl_global_cleanup moved to LLCurl::initClass() diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index dd4e3a6300..231cb7ca8f 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -228,6 +228,12 @@ static void request(  	LLPumpIO::chain_t chain;  	LLURLRequest* req = new LLURLRequest(method, url); +	if(!req->isValid())//failed +	{ +		delete req ; +		return ; +	} +  	req->setSSLVerifyCallback(LLHTTPClient::getCertVerifyCallback(), (void *)req); @@ -423,7 +429,9 @@ static LLSD blocking_request(  {  	lldebugs << "blockingRequest of " << url << llendl;  	char curl_error_buffer[CURL_ERROR_SIZE] = "\0"; -	CURL* curlp = curl_easy_init(); +	CURL* curlp = LLCurl::newEasyHandle(); +	llassert_always(curlp != NULL) ; +  	LLHTTPBuffer http_buffer;  	std::string body_str; @@ -517,7 +525,7 @@ static LLSD blocking_request(  	}  	// * Cleanup -	curl_easy_cleanup(curlp); +	LLCurl::deleteEasyHandle(curlp);  	return response;  } diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 73e8a69085..987f386aa3 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -818,6 +818,8 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(    			// Copy everything after mLast read to the out.  			LLBufferArray::segment_iterator_t seg_iter; + +			buffer->lock();  			seg_iter = buffer->splitAfter(mLastRead);  			if(seg_iter != buffer->endSegment())  			{ @@ -838,7 +840,7 @@ LLIOPipe::EStatus LLHTTPResponder::process_impl(  				}  #endif  			} - +			buffer->unlock();  			//  			// *FIX: get rid of extra bytes off the end  			// diff --git a/indra/llmessage/lliopipe.cpp b/indra/llmessage/lliopipe.cpp index 6e4eec74a6..8f827f7a30 100644 --- a/indra/llmessage/lliopipe.cpp +++ b/indra/llmessage/lliopipe.cpp @@ -75,6 +75,12 @@ LLIOPipe::~LLIOPipe()  	//lldebugs << "destroying LLIOPipe" << llendl;  } +//virtual  +bool LLIOPipe::isValid()  +{ +	return true ; +} +  // static  std::string LLIOPipe::lookupStatusString(EStatus status)  { diff --git a/indra/llmessage/lliopipe.h b/indra/llmessage/lliopipe.h index 8e656b6da1..cbd17b5a3d 100644 --- a/indra/llmessage/lliopipe.h +++ b/indra/llmessage/lliopipe.h @@ -231,6 +231,8 @@ public:  	 */  	virtual ~LLIOPipe(); +	virtual bool isValid() ; +  protected:  	/**  	 * @brief Base Constructor. diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 54ceab3422..d5b4d45821 100644 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -445,6 +445,7 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(  	// efficient - not only because writev() is better, but also  	// because we won't have to do as much work to find the start  	// address. +	buffer->lock();  	LLBufferArray::segment_iterator_t it;  	LLBufferArray::segment_iterator_t end = buffer->endSegment();  	LLSegment segment; @@ -524,6 +525,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(  		}  	} +	buffer->unlock(); +  	PUMP_DEBUG;  	if(done && eos)  	{ diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index a8d2a0a224..f3ef4f2684 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -195,7 +195,7 @@ bool LLPumpIO::prime(apr_pool_t* pool)  	return ((pool == NULL) ? false : true);  } -bool LLPumpIO::addChain(const chain_t& chain, F32 timeout) +bool LLPumpIO::addChain(const chain_t& chain, F32 timeout, bool has_curl_request)  {  	LLMemType m1(LLMemType::MTYPE_IO_PUMP);  	if(chain.empty()) return false; @@ -204,8 +204,10 @@ bool LLPumpIO::addChain(const chain_t& chain, F32 timeout)  	LLScopedLock lock(mChainsMutex);  #endif  	LLChainInfo info; +	info.mHasCurlRequest = has_curl_request;  	info.setTimeoutSeconds(timeout);  	info.mData = LLIOPipe::buffer_ptr_t(new LLBufferArray); +	info.mData->setThreaded(has_curl_request);  	LLLinkInfo link;  #if LL_DEBUG_PIPE_TYPE_IN_PUMP  	lldebugs << "LLPumpIO::addChain() " << chain[0] << " '" @@ -440,6 +442,15 @@ void LLPumpIO::pump()  static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO"); +LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain)  +{ +	std::for_each( +				(*run_chain).mDescriptors.begin(), +				(*run_chain).mDescriptors.end(), +				ll_delete_apr_pollset_fd_client_data()); +	return mRunningChains.erase(run_chain); +} +  //timeout is in microseconds  void LLPumpIO::pump(const S32& poll_timeout)  { @@ -585,10 +596,16 @@ void LLPumpIO::pump(const S32& poll_timeout)  //						<< (*run_chain).mChainLinks[0].mPipe  //						<< " because we reached the end." << llendl;  #endif -				run_chain = mRunningChains.erase(run_chain); +				run_chain = removeRunningChain(run_chain);  				continue;  			}  		} +		else if(isChainExpired(*run_chain)) +		{ +			run_chain = removeRunningChain(run_chain); +			continue; +		} +  		PUMP_DEBUG;  		if((*run_chain).mLock)  		{ @@ -696,11 +713,7 @@ void LLPumpIO::pump(const S32& poll_timeout)  			PUMP_DEBUG;  			// This chain is done. Clean up any allocated memory and  			// erase the chain info. -			std::for_each( -				(*run_chain).mDescriptors.begin(), -				(*run_chain).mDescriptors.end(), -				ll_delete_apr_pollset_fd_client_data()); -			run_chain = mRunningChains.erase(run_chain); +			run_chain = removeRunningChain(run_chain);  			// *NOTE: may not always need to rebuild the pollset.  			mRebuildPollset = true; @@ -1095,6 +1108,24 @@ void LLPumpIO::processChain(LLChainInfo& chain)  	PUMP_DEBUG;  } +bool LLPumpIO::isChainExpired(LLChainInfo& chain) +{ +	if(!chain.mHasCurlRequest) +	{ +		return false ; +	} + +	for(links_t::iterator iter = chain.mChainLinks.begin(); iter != chain.mChainLinks.end(); ++iter) +	{ +		if(!(*iter).mPipe->isValid()) +		{ +			return true ; +		} +	} + +	return false ; +} +  bool LLPumpIO::handleChainError(  	LLChainInfo& chain,  	LLIOPipe::EStatus error) @@ -1136,6 +1167,9 @@ bool LLPumpIO::handleChainError(  #endif  			keep_going = false;  			break; +		case LLIOPipe::STATUS_EXPIRED: +			keep_going = false; +			break ;  		default:  			if(LLIOPipe::isSuccess(error))  			{ @@ -1157,7 +1191,8 @@ bool LLPumpIO::handleChainError(  LLPumpIO::LLChainInfo::LLChainInfo() :  	mInit(false),  	mLock(0), -	mEOS(false) +	mEOS(false), +	mHasCurlRequest(false)  {  	LLMemType m1(LLMemType::MTYPE_IO_PUMP);  	mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS); diff --git a/indra/llmessage/llpumpio.h b/indra/llmessage/llpumpio.h index 9303c9d7fc..d2c5d37571 100644 --- a/indra/llmessage/llpumpio.h +++ b/indra/llmessage/llpumpio.h @@ -111,9 +111,10 @@ public:  	 * @param chain The pipes for the chain  	 * @param timeout The number of seconds in the future to  	 * expire. Pass in 0.0f to never expire. +	 * @param has_curl_request The chain contains LLURLRequest if true.  	 * @return Returns true if anything was added to the pump.  	 */ -	bool addChain(const chain_t& chain, F32 timeout); +	bool addChain(const chain_t& chain, F32 timeout, bool has_curl_request = false);  	/**   	 * @brief Struct to associate a pipe with it's buffer io indexes. @@ -356,12 +357,13 @@ protected:  		// basic member data  		bool mInit; +		bool mEOS; +		bool mHasCurlRequest;  		S32 mLock;  		LLFrameTimer mTimer;  		links_t::iterator mHead;  		links_t mChainLinks; -		LLIOPipe::buffer_ptr_t mData; -		bool mEOS; +		LLIOPipe::buffer_ptr_t mData;		  		LLSD mContext;  		// tracking inside the pump @@ -402,7 +404,7 @@ protected:  protected:  	void initialize(apr_pool_t* pool);  	void cleanup(); - +	current_chain_t removeRunningChain(current_chain_t& chain) ;  	/**   	 * @brief Given the internal state of the chains, rebuild the pollset  	 * @see setConditional() @@ -429,6 +431,9 @@ protected:  	 */  	bool handleChainError(LLChainInfo& chain, LLIOPipe::EStatus error); +	//if the chain is expired, remove it +	bool isChainExpired(LLChainInfo& chain) ; +  public:  	/**   	 * @brief Return number of running chains. diff --git a/indra/llmessage/llsdrpcclient.h b/indra/llmessage/llsdrpcclient.h index 9fb49a5c33..0cecf4f688 100644 --- a/indra/llmessage/llsdrpcclient.h +++ b/indra/llmessage/llsdrpcclient.h @@ -240,9 +240,16 @@ public:  	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const  	{  		lldebugs << "LLSDRPCClientFactory::build" << llendl; -		LLIOPipe::ptr_t service(new Client); -		chain.push_back(service);  		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST)); +		if(!http->isValid()) +		{ +			llwarns << "Creating LLURLRequest failed." << llendl ; +			delete http; +			return false; +		} + +		LLIOPipe::ptr_t service(new Client); +		chain.push_back(service);		  		LLIOPipe::ptr_t http_pipe(http);  		http->addHeader("Content-Type: text/llsd");  		if(mURL.empty()) @@ -283,9 +290,16 @@ public:  	virtual bool build(LLPumpIO::chain_t& chain, LLSD context) const  	{  		lldebugs << "LLXMLSDRPCClientFactory::build" << llendl; -		LLIOPipe::ptr_t service(new Client); -		chain.push_back(service); +  		LLURLRequest* http(new LLURLRequest(LLURLRequest::HTTP_POST)); +		if(!http->isValid()) +		{ +			llwarns << "Creating LLURLRequest failed." << llendl ; +			delete http; +			return false ; +		} +		LLIOPipe::ptr_t service(new Client); +		chain.push_back(service);		  		LLIOPipe::ptr_t http_pipe(http);  		http->addHeader("Content-Type: text/xml");  		if(mURL.empty()) diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 261e57e79e..a16f5c7bf0 100644 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -83,6 +83,12 @@ LLURLRequestDetail::LLURLRequestDetail() :  {  	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);  	mCurlRequest = new LLCurlEasyRequest(); +	 +	if(!mCurlRequest->isValid()) //failed. +	{ +		delete mCurlRequest ; +		mCurlRequest = NULL ; +	}  }  LLURLRequestDetail::~LLURLRequestDetail() @@ -250,12 +256,24 @@ void LLURLRequest::allowCookies()  	mDetail->mCurlRequest->setoptString(CURLOPT_COOKIEFILE, "");  } +//virtual  +bool LLURLRequest::isValid()  +{ +	return mDetail->mCurlRequest && mDetail->mCurlRequest->isValid();  +} +  // virtual  LLIOPipe::EStatus LLURLRequest::handleError(  	LLIOPipe::EStatus status,  	LLPumpIO* pump)  {  	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST); +	 +	if(!isValid()) +	{ +		return STATUS_EXPIRED ; +	} +  	if(mCompletionCallback && pump)  	{  		LLURLRequestComplete* complete = NULL; @@ -441,6 +459,12 @@ void LLURLRequest::initialize()  	LLMemType m1(LLMemType::MTYPE_IO_URL_REQUEST);  	mState = STATE_INITIALIZED;  	mDetail = new LLURLRequestDetail; + +	if(!isValid()) +	{ +		return ; +	} +  	mDetail->mCurlRequest->setopt(CURLOPT_NOSIGNAL, 1);  	mDetail->mCurlRequest->setWriteCallback(&downCallback, (void*)this);  	mDetail->mCurlRequest->setReadCallback(&upCallback, (void*)this); diff --git a/indra/llmessage/llurlrequest.h b/indra/llmessage/llurlrequest.h index ec5c2c1941..44d358d906 100644 --- a/indra/llmessage/llurlrequest.h +++ b/indra/llmessage/llurlrequest.h @@ -188,6 +188,8 @@ public:  	 */  	void allowCookies(); +	/*virtual*/ bool isValid() ; +  public:  	/**   	 * @brief Give this pipe a chance to handle a generated error diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index cd827f5091..03a9884c2b 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -1434,6 +1434,8 @@ void LLRender::loadIdentity()  	flush();  	{ +		llassert_always(mMatrixMode < NUM_MATRIX_MODES) ; +  		mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();  		mMatHash[mMatrixMode]++;  	} diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 9a15b65f83..2e4c537942 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -162,6 +162,7 @@ set(viewer_SOURCE_FILES      llfavoritesbar.cpp      llfeaturemanager.cpp      llfilepicker.cpp +    llfilteredpathfindinglinksets.cpp      llfilteredwearablelist.cpp      llfirstuse.cpp      llflexibleobject.cpp @@ -415,6 +416,7 @@ set(viewer_SOURCE_FILES      llparcelselection.cpp      llparticipantlist.cpp      llpatchvertexarray.cpp +    llpathfindinglinkset.cpp      llphysicsmotion.cpp      llphysicsshapebuilderutil.cpp      llplacesinventorybridge.cpp @@ -721,6 +723,7 @@ set(viewer_HEADER_FILES      llfavoritesbar.h      llfeaturemanager.h      llfilepicker.h +    llfilteredpathfindinglinksets.h      llfilteredwearablelist.h      llfirstuse.h      llflexibleobject.h @@ -963,6 +966,7 @@ set(viewer_HEADER_FILES      llparcelselection.h      llparticipantlist.h      llpatchvertexarray.h +    llpathfindinglinkset.h      llphysicsmotion.h      llphysicsshapebuilderutil.h      llplacesinventorybridge.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 28ba9fd704..ea00a0204d 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -1828,6 +1828,28 @@        <key>Value</key>        <integer>0</integer>      </map> +  <key>CurlMaximumNumberOfHandles</key> +  <map> +    <key>Comment</key> +    <string>Maximum number of handles curl can use (requires restart)</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>S32</string> +    <key>Value</key> +    <integer>256</integer> +  </map> +  <key>CurlRequestTimeOut</key> +  <map> +    <key>Comment</key> +    <string>Max idle time of a curl request before killed (requires restart)</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>F32</string> +    <key>Value</key> +    <real>120.0</real> +  </map>    <key>CurlUseMultipleThreads</key>    <map>      <key>Comment</key> diff --git a/indra/newview/llagentwearablesfetch.cpp b/indra/newview/llagentwearablesfetch.cpp index 1edc96e165..4097ff707c 100644 --- a/indra/newview/llagentwearablesfetch.cpp +++ b/indra/newview/llagentwearablesfetch.cpp @@ -111,6 +111,12 @@ void LLInitialWearablesFetch::add(InitialWearableData &data)  void LLInitialWearablesFetch::processContents()  { +	if(!gAgentAvatarp) //no need to process wearables if the agent avatar is deleted. +	{ +		delete this; +		return ; +	} +  	// Fetch the wearable items from the Current Outfit Folder  	LLInventoryModel::cat_array_t cat_array;  	LLInventoryModel::item_array_t wearable_array; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 172eb834b4..261553599b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -723,7 +723,9 @@ bool LLAppViewer::init()      // *NOTE:Mani - LLCurl::initClass is not thread safe.       // Called before threads are created. -    LLCurl::initClass(gSavedSettings.getBOOL("CurlUseMultipleThreads")); +    LLCurl::initClass(gSavedSettings.getF32("CurlRequestTimeOut"),  +						gSavedSettings.getS32("CurlMaximumNumberOfHandles"),  +						gSavedSettings.getBOOL("CurlUseMultipleThreads"));  	LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ;      LLMachineID::init(); diff --git a/indra/newview/llfilteredpathfindinglinksets.cpp b/indra/newview/llfilteredpathfindinglinksets.cpp new file mode 100644 index 0000000000..aaff2bcc68 --- /dev/null +++ b/indra/newview/llfilteredpathfindinglinksets.cpp @@ -0,0 +1,313 @@ +/** 
 + * @file llfilteredpathfindinglinksets.h
 + * @author William Todd Stinson
 + * @brief Class to implement the filtering of a set of pathfinding linksets
 + *
 + * $LicenseInfo:firstyear=2002&license=viewerlgpl$
 + * Second Life Viewer Source Code
 + * Copyright (C) 2010, 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 "llviewerprecompiledheaders.h"
 +
 +#include <string>
 +#include <map>
 +
 +#include "llsd.h"
 +#include "lluuid.h"
 +#include "llpathfindinglinkset.h"
 +#include "llfilteredpathfindinglinksets.h"
 +
 +//---------------------------------------------------------------------------
 +// FilterString
 +//---------------------------------------------------------------------------
 +
 +FilterString::FilterString()
 +	: mFilter(),
 +	mUpperFilter()
 +{
 +}
 +
 +FilterString::FilterString(const std::string& pFilter)
 +	: mFilter(pFilter),
 +	mUpperFilter()
 +{
 +	LLStringUtil::trim(mFilter);
 +	mUpperFilter = mFilter;
 +	if (!mUpperFilter.empty())
 +	{
 +		LLStringUtil::toUpper(mUpperFilter);
 +	}
 +}
 +
 +FilterString::~FilterString()
 +{
 +}
 +
 +const std::string& FilterString::get() const
 +{
 +	return mFilter;
 +}
 +
 +bool FilterString::set(const std::string& pFilter)
 +{
 +	std::string newFilter(pFilter);
 +	LLStringUtil::trim(newFilter);
 +	bool didFilterChange = (mFilter.compare(newFilter) != 0);
 +	if (didFilterChange)
 +	{
 +		mFilter = newFilter;
 +		mUpperFilter = newFilter;
 +		LLStringUtil::toUpper(mUpperFilter);
 +	}
 +
 +	return didFilterChange;
 +}
 +
 +void FilterString::clear()
 +{
 +	mFilter.clear();
 +	mUpperFilter.clear();
 +}
 +
 +bool FilterString::isActive() const
 +{
 +	return !mFilter.empty();
 +}
 +
 +bool FilterString::doesMatch(const std::string& pTestString) const
 +{
 +	bool doesMatch = true;
 +
 +	if (isActive())
 +	{
 +		std::string upperTestString(pTestString);
 +		LLStringUtil::toUpper(upperTestString);
 +		doesMatch = (upperTestString.find(mUpperFilter) != std::string::npos);
 +	}
 +
 +	return doesMatch;
 +}
 +
 +//---------------------------------------------------------------------------
 +// LLFilteredPathfindingLinksets
 +//---------------------------------------------------------------------------
 +
 +LLFilteredPathfindingLinksets::LLFilteredPathfindingLinksets()
 +	: mAllLinksets(),
 +	mFilteredLinksets(),
 +	mIsFiltersDirty(false),
 +	mNameFilter(),
 +	mDescriptionFilter(),
 +	mIsWalkableFilter(true),
 +	mIsObstacleFilter(true),
 +	mIsIgnoredFilter(true)
 +{
 +}
 +
 +LLFilteredPathfindingLinksets::LLFilteredPathfindingLinksets(const LLSD& pLinksetItems)
 +	: mAllLinksets(),
 +	mFilteredLinksets(),
 +	mIsFiltersDirty(false),
 +	mNameFilter(),
 +	mDescriptionFilter(),
 +	mIsWalkableFilter(true),
 +	mIsObstacleFilter(true),
 +	mIsIgnoredFilter(true)
 +{
 +	setPathfindingLinksets(pLinksetItems);
 +}
 +
 +LLFilteredPathfindingLinksets::LLFilteredPathfindingLinksets(const LLFilteredPathfindingLinksets& pOther)
 +	: mAllLinksets(pOther.mAllLinksets),
 +	mFilteredLinksets(pOther.mFilteredLinksets),
 +	mIsFiltersDirty(pOther.mIsFiltersDirty),
 +	mNameFilter(pOther.mNameFilter),
 +	mDescriptionFilter(pOther.mDescriptionFilter),
 +	mIsWalkableFilter(pOther.mIsWalkableFilter),
 +	mIsObstacleFilter(pOther.mIsObstacleFilter),
 +	mIsIgnoredFilter(pOther.mIsIgnoredFilter)
 +{
 +}
 +
 +LLFilteredPathfindingLinksets::~LLFilteredPathfindingLinksets()
 +{
 +	clearPathfindingLinksets();
 +}
 +
 +void LLFilteredPathfindingLinksets::setPathfindingLinksets(const LLSD& pLinksetItems)
 +{
 +	clearPathfindingLinksets();
 +
 +	for (LLSD::map_const_iterator linksetItemIter = pLinksetItems.beginMap();
 +		linksetItemIter != pLinksetItems.endMap(); ++linksetItemIter)
 +	{
 +		const std::string& uuid(linksetItemIter->first);
 +		const LLSD& linksetData = linksetItemIter->second;
 +		LLPathfindingLinkset linkset(uuid, linksetData);
 +
 +		mAllLinksets.insert(std::pair<std::string, LLPathfindingLinkset>(uuid, linkset));
 +	}
 +
 +	mIsFiltersDirty = true;
 +}
 +
 +void LLFilteredPathfindingLinksets::updatePathfindingLinksets(const LLSD& pLinksetItems)
 +{
 +	for (LLSD::map_const_iterator linksetItemIter = pLinksetItems.beginMap();
 +		linksetItemIter != pLinksetItems.endMap(); ++linksetItemIter)
 +	{
 +		const std::string& uuid(linksetItemIter->first);
 +		const LLSD& linksetData = linksetItemIter->second;
 +		LLPathfindingLinkset linkset(uuid, linksetData);
 +
 +		PathfindingLinksetMap::iterator linksetIter = mAllLinksets.find(uuid);
 +		if (linksetIter == mAllLinksets.end())
 +		{
 +			mAllLinksets.insert(std::pair<std::string, LLPathfindingLinkset>(uuid, linkset));
 +		}
 +		else
 +		{
 +			linksetIter->second = linkset;
 +		}
 +	}
 +
 +	mIsFiltersDirty = true;
 +}
 +
 +void LLFilteredPathfindingLinksets::clearPathfindingLinksets()
 +{
 +	mAllLinksets.clear();
 +	mFilteredLinksets.clear();
 +	mIsFiltersDirty = false;
 +}
 +
 +const LLFilteredPathfindingLinksets::PathfindingLinksetMap& LLFilteredPathfindingLinksets::getAllLinksets() const
 +{
 +	return mAllLinksets;
 +}
 +
 +const LLFilteredPathfindingLinksets::PathfindingLinksetMap& LLFilteredPathfindingLinksets::getFilteredLinksets()
 +{
 +	if (!isFiltersActive())
 +	{
 +		return mAllLinksets;
 +	}
 +	else
 +	{
 +		applyFilters();
 +		return mFilteredLinksets;
 +	}
 +}
 +
 +BOOL LLFilteredPathfindingLinksets::isFiltersActive() const
 +{
 +	return (mNameFilter.isActive() || mDescriptionFilter.isActive() || !mIsWalkableFilter || !mIsObstacleFilter || !mIsIgnoredFilter);
 +}
 +
 +void LLFilteredPathfindingLinksets::setNameFilter(const std::string& pNameFilter)
 +{
 +	mIsFiltersDirty = (mNameFilter.set(pNameFilter) || mIsFiltersDirty);
 +}
 +
 +const std::string& LLFilteredPathfindingLinksets::getNameFilter() const
 +{
 +	return mNameFilter.get();
 +}
 +
 +void LLFilteredPathfindingLinksets::setDescriptionFilter(const std::string& pDescriptionFilter)
 +{
 +	mIsFiltersDirty = (mDescriptionFilter.set(pDescriptionFilter) || mIsFiltersDirty);
 +}
 +
 +const std::string& LLFilteredPathfindingLinksets::getDescriptionFilter() const
 +{
 +	return mDescriptionFilter.get();
 +}
 +
 +void LLFilteredPathfindingLinksets::setWalkableFilter(BOOL pWalkableFilter)
 +{
 +	mIsFiltersDirty = (mIsFiltersDirty || (mIsWalkableFilter == pWalkableFilter));
 +	mIsWalkableFilter = pWalkableFilter;
 +}
 +
 +BOOL LLFilteredPathfindingLinksets::isWalkableFilter() const
 +{
 +	return mIsWalkableFilter;
 +}
 +
 +void LLFilteredPathfindingLinksets::setObstacleFilter(BOOL pObstacleFilter)
 +{
 +	mIsFiltersDirty = (mIsFiltersDirty || (mIsObstacleFilter == pObstacleFilter));
 +	mIsObstacleFilter = pObstacleFilter;
 +}
 +
 +BOOL LLFilteredPathfindingLinksets::isObstacleFilter() const
 +{
 +	return mIsObstacleFilter;
 +}
 +
 +void LLFilteredPathfindingLinksets::setIgnoredFilter(BOOL pIgnoredFilter)
 +{
 +	mIsFiltersDirty = (mIsFiltersDirty || (mIsIgnoredFilter == pIgnoredFilter));
 +	mIsIgnoredFilter = pIgnoredFilter;
 +}
 +
 +BOOL LLFilteredPathfindingLinksets::isIgnoredFilter() const
 +{
 +	return mIsIgnoredFilter;
 +}
 +
 +void LLFilteredPathfindingLinksets::clearFilters()
 +{
 +	mNameFilter.clear();
 +	mDescriptionFilter.clear();
 +	mIsWalkableFilter = true;
 +	mIsObstacleFilter = true;
 +	mIsIgnoredFilter = true;
 +	mIsFiltersDirty = false;
 +}
 +
 +void LLFilteredPathfindingLinksets::applyFilters()
 +{
 +	mFilteredLinksets.clear();
 +
 +	for (PathfindingLinksetMap::const_iterator linksetIter = mAllLinksets.begin();
 +		linksetIter != mAllLinksets.end(); ++linksetIter)
 +	{
 +		const std::string& uuid(linksetIter->first);
 +		const LLPathfindingLinkset& linkset(linksetIter->second);
 +		if (doesMatchFilters(linkset))
 +		{
 +			mFilteredLinksets.insert(std::pair<std::string, LLPathfindingLinkset>(uuid, linkset));
 +		}
 +	}
 +
 +	mIsFiltersDirty = false;
 +}
 +
 +BOOL LLFilteredPathfindingLinksets::doesMatchFilters(const LLPathfindingLinkset& pLinkset) const
 +{
 +	return (((mIsWalkableFilter && (pLinkset.getPathState() == LLPathfindingLinkset::kWalkable)) ||
 +			 (mIsObstacleFilter && (pLinkset.getPathState() == LLPathfindingLinkset::kObstacle)) ||
 +			 (mIsIgnoredFilter && (pLinkset.getPathState() == LLPathfindingLinkset::kIgnored))) &&
 +			(!mNameFilter.isActive() || mNameFilter.doesMatch(pLinkset.getName())) &&
 +			(!mDescriptionFilter.isActive() || mDescriptionFilter.doesMatch(pLinkset.getDescription())));
 +}
 diff --git a/indra/newview/llfilteredpathfindinglinksets.h b/indra/newview/llfilteredpathfindinglinksets.h new file mode 100644 index 0000000000..de9b3a5e15 --- /dev/null +++ b/indra/newview/llfilteredpathfindinglinksets.h @@ -0,0 +1,111 @@ +/** 
 + * @file llfilteredpathfindinglinksets.h
 + * @author William Todd Stinson
 + * @brief Class to implement the filtering of a set of pathfinding linksets
 + *
 + * $LicenseInfo:firstyear=2002&license=viewerlgpl$
 + * Second Life Viewer Source Code
 + * Copyright (C) 2010, 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_FILTEREDPATHFINDINGLINKSETS_H
 +#define LL_FILTEREDPATHFINDINGLINKSETS_H
 +
 +#include <string>
 +#include <map>
 +
 +class LLSD;
 +class LLPathfindingLinkset;
 +
 +class FilterString
 +{
 +public:
 +	FilterString();
 +	FilterString(const std::string& pFilter);
 +	virtual ~FilterString();
 +
 +	const std::string& get() const;
 +	bool               set(const std::string& pFilter);
 +	void               clear();
 +
 +	bool               isActive() const;
 +	bool               doesMatch(const std::string& pTestString) const;
 +
 +protected:
 +
 +private:
 +	std::string mFilter;
 +	std::string mUpperFilter;
 +};
 +
 +class LLFilteredPathfindingLinksets
 +{
 +public:
 +	typedef std::map<std::string, LLPathfindingLinkset> PathfindingLinksetMap;
 +
 +	LLFilteredPathfindingLinksets();
 +	LLFilteredPathfindingLinksets(const LLSD& pLinksetItems);
 +	LLFilteredPathfindingLinksets(const LLFilteredPathfindingLinksets& pOther);
 +	virtual ~LLFilteredPathfindingLinksets();
 +
 +	void                         setPathfindingLinksets(const LLSD& pLinksetItems);
 +	void                         updatePathfindingLinksets(const LLSD& pLinksetItems);
 +	void                         clearPathfindingLinksets();
 +
 +	const PathfindingLinksetMap& getAllLinksets() const;
 +	const PathfindingLinksetMap& getFilteredLinksets();
 +
 +	BOOL                         isFiltersActive() const;
 +
 +	void                         setNameFilter(const std::string& pNameFilter);
 +	const std::string&           getNameFilter() const;
 +
 +	void                         setDescriptionFilter(const std::string& pDescriptionFilter);
 +	const std::string&           getDescriptionFilter() const;
 +
 +	void                         setWalkableFilter(BOOL pWalkableFilter);
 +	BOOL                         isWalkableFilter() const;
 +
 +	void                         setObstacleFilter(BOOL pObstacleFilter);
 +	BOOL                         isObstacleFilter() const;
 +
 +	void                         setIgnoredFilter(BOOL pIgnoredFilter);
 +	BOOL                         isIgnoredFilter() const;
 +
 +	void                         clearFilters();
 +
 +protected:
 +
 +private:
 +	PathfindingLinksetMap mAllLinksets;
 +	PathfindingLinksetMap mFilteredLinksets;
 +
 +	bool                  mIsFiltersDirty;
 +	FilterString          mNameFilter;
 +	FilterString          mDescriptionFilter;
 +	BOOL                  mIsWalkableFilter;
 +	BOOL                  mIsObstacleFilter;
 +	BOOL                  mIsIgnoredFilter;
 +
 +	void applyFilters();
 +	BOOL doesMatchFilters(const LLPathfindingLinkset& pLinkset) const;
 +};
 +
 +#endif // LL_FILTEREDPATHFINDINGLINKSETS_H
 diff --git a/indra/newview/llfloaterpathfindingconsole.cpp b/indra/newview/llfloaterpathfindingconsole.cpp index fce67c4171..50edc55d76 100644 --- a/indra/newview/llfloaterpathfindingconsole.cpp +++ b/indra/newview/llfloaterpathfindingconsole.cpp @@ -313,6 +313,12 @@ void LLFloaterPathfindingConsole::setHasNavMeshReceived()  {  	std::string str = getString("navmesh_fetch_complete_available");  	mPathfindingStatus->setText((LLStringExplicit)str); +	//check to see if all regions are done loading and they are then stitch the navmeshes together +	--mNavMeshCnt; +	if ( mNavMeshCnt == 0 ) +	{ +		//LLPathingLib::getInstance()->stitchNavMeshes(); +	}  }  void LLFloaterPathfindingConsole::setHasNoNavMesh() @@ -335,7 +341,10 @@ LLFloaterPathfindingConsole::LLFloaterPathfindingConsole(const LLSD& pSeed)  	mTerrainMaterialA(NULL),  	mTerrainMaterialB(NULL),  	mTerrainMaterialC(NULL), -	mTerrainMaterialD(NULL) +	mTerrainMaterialD(NULL), +	mNavMeshCnt(0), +	mHasStartPoint(false), +	mHasEndPoint(false)  {  	for (int i=0;i<MAX_OBSERVERS;++i)  	{ @@ -353,12 +362,7 @@ void LLFloaterPathfindingConsole::onOpen(const LLSD& pKey)  	if ( !LLPathingLib::getInstance() )  	{  		LLPathingLib::initSystem(); -	} -	//prep# test remove -	//LLSD content; -	//LLPathingLib::getInstance()->extractNavMeshSrcFromLLSD( content ); -	//return true; -	//prep# end test +	}	  	if ( LLPathingLib::getInstance() == NULL )  	{   		std::string str = getString("navmesh_library_not_implemented"); @@ -370,6 +374,8 @@ void LLFloaterPathfindingConsole::onOpen(const LLSD& pKey)  	else  	{		  		mCurrentMDO = 0; +		mNavMeshCnt = 0; +  		//make sure the region is essentially enabled for navmesh support  		std::string capability = "RetrieveNavMeshSrc"; @@ -383,7 +389,15 @@ void LLFloaterPathfindingConsole::onOpen(const LLSD& pKey)  		shift.push_back( CURRENT_REGION );  		//pCurrentRegion->getNeighboringRegionsStatus( shift ); +		//If the navmesh shift ops and the total region counts do not match - use the current region, only. +		if ( shift.size() != regions.size() ) +		{ +			shift.clear();regions.clear(); +			regions.push_back( pCurrentRegion ); +			shift.push_back( CURRENT_REGION );				 +		}  		int regionCnt = regions.size(); +		mNavMeshCnt = regionCnt;  		for ( int i=0; i<regionCnt; ++i )  		{  			std::string url = regions[i]->getCapability( capability ); @@ -399,6 +413,7 @@ void LLFloaterPathfindingConsole::onOpen(const LLSD& pKey)  			}				  			else  			{ +				--mNavMeshCnt;  				std::string str = getString("navmesh_region_not_enabled");  				LLStyle::Params styleParams;  				styleParams.color = LLUIColorTable::instance().getColor("DrYellow"); @@ -432,7 +447,7 @@ void LLFloaterPathfindingConsole::onShowExcludeVolumesToggle()  	LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance();  	if (llPathingLibInstance != NULL)  	{ -		llPathingLibInstance->setRenderNavMeshandShapes(checkBoxValue); +		llPathingLibInstance->setRenderShapes(checkBoxValue);  	}  	else  	{ @@ -445,15 +460,33 @@ void LLFloaterPathfindingConsole::onShowPathToggle()  {  	BOOL checkBoxValue = mShowPathCheckBox->get(); -	llwarns << "functionality has not yet been implemented to toggle '" -		<< mShowPathCheckBox->getLabel() << "' to " -		<< (checkBoxValue ? "ON" : "OFF") << llendl; +	LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance(); +	if (llPathingLibInstance != NULL) +	{ +		llPathingLibInstance->setRenderPath(checkBoxValue); +	} +	else +	{ +		mShowPathCheckBox->set(FALSE); +		llwarns << "cannot find LLPathingLib instance" << llendl; +	}  }  void LLFloaterPathfindingConsole::onShowWaterPlaneToggle()  {  	BOOL checkBoxValue = mShowWaterPlaneCheckBox->get(); +	LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance(); +	if (llPathingLibInstance != NULL) +	{ +		llPathingLibInstance->setRenderWaterPlane(checkBoxValue); +	} +	else +	{ +		mShowWaterPlaneCheckBox->set(FALSE); +		llwarns << "cannot find LLPathingLib instance" << llendl; +	} +  	llwarns << "functionality has not yet been implemented to toggle '"  		<< mShowWaterPlaneCheckBox->getLabel() << "' to "  		<< (checkBoxValue ? "ON" : "OFF") << llendl; @@ -461,21 +494,27 @@ void LLFloaterPathfindingConsole::onShowWaterPlaneToggle()  void LLFloaterPathfindingConsole::onRegionOverlayDisplaySwitch()  { -	switch (getRegionOverlayDisplay()) +	LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance(); +	if (llPathingLibInstance != NULL)  	{ -	case kRenderOverlayOnFixedPhysicsGeometry : -		llwarns << "functionality has not yet been implemented to toggle '" -			<< mRegionOverlayDisplayRadioGroup->getName() << "' to RenderOverlayOnFixedPhysicsGeometry" -			<< llendl; -		break; -	case kRenderOverlayOnAllRenderableGeometry : -		llwarns << "functionality has not yet been implemented to toggle '" -			<< mRegionOverlayDisplayRadioGroup->getName() << "' to RenderOverlayOnAllRenderableGeometry" -			<< llendl; -		break; -	default : -		llassert(0); -		break; +		switch (getRegionOverlayDisplay()) +		{ +		case kRenderOverlayOnFixedPhysicsGeometry : +			llPathingLibInstance->setRenderOverlayMode(false); +			break; +		case kRenderOverlayOnAllRenderableGeometry : +			llPathingLibInstance->setRenderOverlayMode(true); +			break; +		default : +			llPathingLibInstance->setRenderOverlayMode(false); +			llassert(0); +			break; +		} +	} +	else +	{ +		this->setRegionOverlayDisplay(kRenderOverlayOnFixedPhysicsGeometry); +		llwarns << "cannot find LLPathingLib instance" << llendl;  	}  } @@ -484,19 +523,10 @@ void LLFloaterPathfindingConsole::onPathSelectionSwitch()  	switch (getPathSelectionState())  	{  	case kPathSelectNone : -		llwarns << "functionality has not yet been implemented to toggle '" -			<< mPathSelectionRadioGroup->getName() << "' to PathSelectNone" -			<< llendl;  		break;  	case kPathSelectStartPoint : -		llwarns << "functionality has not yet been implemented to toggle '" -			<< mPathSelectionRadioGroup->getName() << "' to PathSelectStartPoint" -			<< llendl;  		break;  	case kPathSelectEndPoint : -		llwarns << "functionality has not yet been implemented to toggle '" -			<< mPathSelectionRadioGroup->getName() << "' to PathSelectEndPoint" -			<< llendl;  		break;  	default :  		llassert(0); @@ -506,9 +536,7 @@ void LLFloaterPathfindingConsole::onPathSelectionSwitch()  void LLFloaterPathfindingConsole::onCharacterWidthSet()  { -	F32 characterWidth = getCharacterWidth(); -	llwarns << "functionality has not yet been implemented to set '" << mCharacterWidthSlider->getName() -		<< "' to the value (" << characterWidth << ")" << llendl; +	generatePath();  }  void LLFloaterPathfindingConsole::onCharacterTypeSwitch() @@ -586,11 +614,6 @@ void LLFloaterPathfindingConsole::onTerrainMaterialDSet()  } -BOOL LLFloaterPathfindingConsole::allowAllRenderables() const -{ -	return getRegionOverlayDisplay() == kRenderOverlayOnAllRenderableGeometry ? true : false; -} -  void LLFloaterPathfindingConsole::providePathingData( const LLVector3& point1, const LLVector3& point2 )  {  	switch (getPathSelectionState()) @@ -604,18 +627,28 @@ void LLFloaterPathfindingConsole::providePathingData( const LLVector3& point1, c  	case kPathSelectStartPoint :  		mPathData.mStartPointA	= point1;  		mPathData.mEndPointA	= point2; +		mHasStartPoint = true;  		break;  	case kPathSelectEndPoint :  		mPathData.mStartPointB		= point1;  		mPathData.mEndPointB		= point2;		 -		mPathData.mCharacterWidth	= getCharacterWidth(); -		//prep#TODO# possibly consider an alternate behavior - perhaps add a "path" button to submit the data. -		LLPathingLib::getInstance()->generatePath( mPathData ); +		mHasEndPoint = true;  		break;  	default :  		llassert(0);  		break; -	}	 +	} + +	generatePath(); +} + +void LLFloaterPathfindingConsole::generatePath() +{ +	if (mHasStartPoint && mHasEndPoint) +	{ +		mPathData.mCharacterWidth = getCharacterWidth(); +		LLPathingLib::getInstance()->generatePath(mPathData); +	}  } diff --git a/indra/newview/llfloaterpathfindingconsole.h b/indra/newview/llfloaterpathfindingconsole.h index 3ae5e25695..f62fd9742b 100644 --- a/indra/newview/llfloaterpathfindingconsole.h +++ b/indra/newview/llfloaterpathfindingconsole.h @@ -31,13 +31,13 @@  #include "llfloater.h"  #include "llnavmeshstation.h"  #include "LLPathingLib.h" -#include "llcheckboxctrl.h"  class LLSD;  class LLRadioGroup;  class LLSliderCtrl;  class LLLineEditor;  class LLTextBase; +class LLCheckBoxCtrl;  class LLFloaterPathfindingConsole  :	public LLFloater @@ -67,8 +67,6 @@ public:  	} ECharacterType;  	virtual BOOL postBuild(); -	//Accessor to determine whether renderables are allowed -	BOOL allowAllRenderables() const;  	//Populates a data packet that is forwarded onto the LLPathingSystem  	void providePathingData( const LLVector3& point1, const LLVector3& point2 ); @@ -96,8 +94,6 @@ public:      F32                   getTerrainMaterialD() const;      void                  setTerrainMaterialD(F32 pTerrainMaterial); -	BOOL				  getShowPathToggle() const {return mShowPathCheckBox->get(); } -  	void setHasNavMeshReceived();  	void setHasNoNavMesh(); @@ -126,6 +122,7 @@ private:  	void onTerrainMaterialBSet();  	void onTerrainMaterialCSet();  	void onTerrainMaterialDSet(); +	void generatePath();  	LLCheckBoxCtrl *mShowNavMeshCheckBox;  	LLCheckBoxCtrl *mShowExcludeVolumesCheckBox; @@ -143,9 +140,12 @@ private:  	LLNavMeshDownloadObserver	mNavMeshDownloadObserver[10];  	int							mCurrentMDO; +	int							mNavMeshCnt;  	//Container that is populated and subsequently submitted to the LLPathingSystem for processing  	LLPathingLib::PathingPacket		mPathData; +	bool mHasStartPoint; +	bool mHasEndPoint;  };  #endif // LL_LLFLOATERPATHFINDINGCONSOLE_H diff --git a/indra/newview/llfloaterpathfindinglinksets.cpp b/indra/newview/llfloaterpathfindinglinksets.cpp index e8f1401095..4d3581fc60 100644 --- a/indra/newview/llfloaterpathfindinglinksets.cpp +++ b/indra/newview/llfloaterpathfindinglinksets.cpp @@ -32,7 +32,7 @@  #include "v3math.h"
  #include "lltextvalidate.h"
  #include "llagent.h"
 -#include "llfloater.h"
 +#include "llhandle.h"
  #include "llfloaterreg.h"
  #include "lltextbase.h"
  #include "lllineeditor.h"
 @@ -45,6 +45,8 @@  #include "llviewerregion.h"
  #include "llhttpclient.h"
  #include "lluuid.h"
 +#include "llpathfindinglinkset.h"
 +#include "llfilteredpathfindinglinksets.h"
  #define XUI_PATH_STATE_WALKABLE 1
  #define XUI_PATH_STATE_OBSTACLE 2
 @@ -57,7 +59,8 @@  class NavMeshDataGetResponder : public LLHTTPClient::Responder
  {
  public:
 -	NavMeshDataGetResponder(const std::string& pNavMeshDataGetURL, LLFloaterPathfindingLinksets *pLinksetsFloater);
 +	NavMeshDataGetResponder(const std::string& pNavMeshDataGetURL,
 +		const LLHandle<LLFloaterPathfindingLinksets> &pLinksetsHandle);
  	virtual ~NavMeshDataGetResponder();
  	virtual void result(const LLSD& pContent);
 @@ -66,8 +69,8 @@ public:  private:
  	NavMeshDataGetResponder(const NavMeshDataGetResponder& pOther);
 -	std::string                  mNavMeshDataGetURL;
 -	LLFloaterPathfindingLinksets *mLinksetsFloater;
 +	std::string                            mNavMeshDataGetURL;
 +	LLHandle<LLFloaterPathfindingLinksets> mLinksetsFloaterHandle;
  };
  //---------------------------------------------------------------------------
 @@ -77,7 +80,8 @@ private:  class NavMeshDataPutResponder : public LLHTTPClient::Responder
  {
  public:
 -	NavMeshDataPutResponder(const std::string& pNavMeshDataPutURL, LLFloaterPathfindingLinksets *pLinksetsFloater);
 +	NavMeshDataPutResponder(const std::string& pNavMeshDataPutURL,
 +		const LLHandle<LLFloaterPathfindingLinksets> &pLinksetsHandle);
  	virtual ~NavMeshDataPutResponder();
  	virtual void result(const LLSD& pContent);
 @@ -86,670 +90,11 @@ public:  private:
  	NavMeshDataPutResponder(const NavMeshDataPutResponder& pOther);
 -	std::string                  mNavMeshDataPutURL;
 -	LLFloaterPathfindingLinksets *mLinksetsFloater;
 +	std::string                            mNavMeshDataPutURL;
 +	LLHandle<LLFloaterPathfindingLinksets> mLinksetsFloaterHandle;
  };
  //---------------------------------------------------------------------------
 -// PathfindingLinkset
 -//---------------------------------------------------------------------------
 -
 -const S32 PathfindingLinkset::MIN_WALKABILITY_VALUE(0);
 -const S32 PathfindingLinkset::MAX_WALKABILITY_VALUE(100);
 -
 -PathfindingLinkset::PathfindingLinkset(const std::string &pUUID, const LLSD& pNavMeshItem)
 -	: mUUID(pUUID),
 -	mName(),
 -	mDescription(),
 -	mLandImpact(0U),
 -	mLocation(),
 -	mPathState(kIgnored),
 -	mIsPhantom(false),
 -#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	mIsWalkabilityCoefficientsF32(false),
 -#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	mA(MIN_WALKABILITY_VALUE),
 -	mB(MIN_WALKABILITY_VALUE),
 -	mC(MIN_WALKABILITY_VALUE),
 -	mD(MIN_WALKABILITY_VALUE)
 -{
 -	llassert(pNavMeshItem.has("name"));
 -	llassert(pNavMeshItem.get("name").isString());
 -	mName = pNavMeshItem.get("name").asString();
 -
 -	llassert(pNavMeshItem.has("description"));
 -	llassert(pNavMeshItem.get("description").isString());
 -	mDescription = pNavMeshItem.get("description").asString();
 -
 -	llassert(pNavMeshItem.has("landimpact"));
 -	llassert(pNavMeshItem.get("landimpact").isInteger());
 -	llassert(pNavMeshItem.get("landimpact").asInteger() >= 0);
 -	mLandImpact = pNavMeshItem.get("landimpact").asInteger();
 -
 -	llassert(pNavMeshItem.has("permanent"));
 -	llassert(pNavMeshItem.get("permanent").isBoolean());
 -	bool isPermanent = pNavMeshItem.get("permanent").asBoolean();
 -
 -	llassert(pNavMeshItem.has("walkable"));
 -	llassert(pNavMeshItem.get("walkable").isBoolean());
 -	bool isWalkable = pNavMeshItem.get("walkable").asBoolean();
 -
 -	mPathState = getPathState(isPermanent, isWalkable);
 -
 -	llassert(pNavMeshItem.has("phantom"));
 -	llassert(pNavMeshItem.get("phantom").isBoolean());
 -	mIsPhantom = pNavMeshItem.get("phantom").asBoolean();
 -
 -	llassert(pNavMeshItem.has("A"));
 -#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	mIsWalkabilityCoefficientsF32 = pNavMeshItem.get("A").isReal();
 -	if (mIsWalkabilityCoefficientsF32)
 -	{
 -		// Old server-side storage was real
 -		mA = llround(pNavMeshItem.get("A").asReal() * 100.0f);
 -
 -		llassert(pNavMeshItem.has("B"));
 -		llassert(pNavMeshItem.get("B").isReal());
 -		mB = llround(pNavMeshItem.get("B").asReal() * 100.0f);
 -
 -		llassert(pNavMeshItem.has("C"));
 -		llassert(pNavMeshItem.get("C").isReal());
 -		mC = llround(pNavMeshItem.get("C").asReal() * 100.0f);
 -
 -		llassert(pNavMeshItem.has("D"));
 -		llassert(pNavMeshItem.get("D").isReal());
 -		mD = llround(pNavMeshItem.get("D").asReal() * 100.0f);
 -	}
 -	else
 -	{
 -		// New server-side storage will be integer
 -		llassert(pNavMeshItem.get("A").isInteger());
 -		mA = pNavMeshItem.get("A").asInteger();
 -		llassert(mA >= MIN_WALKABILITY_VALUE);
 -		llassert(mA <= MAX_WALKABILITY_VALUE);
 -
 -		llassert(pNavMeshItem.has("B"));
 -		llassert(pNavMeshItem.get("B").isInteger());
 -		mB = pNavMeshItem.get("B").asInteger();
 -		llassert(mB >= MIN_WALKABILITY_VALUE);
 -		llassert(mB <= MAX_WALKABILITY_VALUE);
 -
 -		llassert(pNavMeshItem.has("C"));
 -		llassert(pNavMeshItem.get("C").isInteger());
 -		mC = pNavMeshItem.get("C").asInteger();
 -		llassert(mC >= MIN_WALKABILITY_VALUE);
 -		llassert(mC <= MAX_WALKABILITY_VALUE);
 -
 -		llassert(pNavMeshItem.has("D"));
 -		llassert(pNavMeshItem.get("D").isInteger());
 -		mD = pNavMeshItem.get("D").asInteger();
 -		llassert(mD >= MIN_WALKABILITY_VALUE);
 -		llassert(mD <= MAX_WALKABILITY_VALUE);
 -	}
 -#else // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	llassert(pNavMeshItem.get("A").isInteger());
 -	mA = pNavMeshItem.get("A").asInteger();
 -	llassert(mA >= MIN_WALKABILITY_VALUE);
 -	llassert(mA <= MAX_WALKABILITY_VALUE);
 -
 -	llassert(pNavMeshItem.has("B"));
 -	llassert(pNavMeshItem.get("B").isInteger());
 -	mB = pNavMeshItem.get("B").asInteger();
 -	llassert(mB >= MIN_WALKABILITY_VALUE);
 -	llassert(mB <= MAX_WALKABILITY_VALUE);
 -
 -	llassert(pNavMeshItem.has("C"));
 -	llassert(pNavMeshItem.get("C").isInteger());
 -	mC = pNavMeshItem.get("C").asInteger();
 -	llassert(mC >= MIN_WALKABILITY_VALUE);
 -	llassert(mC <= MAX_WALKABILITY_VALUE);
 -
 -	llassert(pNavMeshItem.has("D"));
 -	llassert(pNavMeshItem.get("D").isInteger());
 -	mD = pNavMeshItem.get("D").asInteger();
 -	llassert(mD >= MIN_WALKABILITY_VALUE);
 -	llassert(mD <= MAX_WALKABILITY_VALUE);
 -#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -
 -	llassert(pNavMeshItem.has("position"));
 -	llassert(pNavMeshItem.get("position").isArray());
 -	mLocation.setValue(pNavMeshItem.get("position"));
 -}
 -
 -PathfindingLinkset::PathfindingLinkset(const PathfindingLinkset& pOther)
 -	: mUUID(pOther.mUUID),
 -	mName(pOther.mName),
 -	mDescription(pOther.mDescription),
 -	mLandImpact(pOther.mLandImpact),
 -	mLocation(pOther.mLocation),
 -	mPathState(pOther.mPathState),
 -	mIsPhantom(pOther.mIsPhantom),
 -#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	mIsWalkabilityCoefficientsF32(pOther.mIsWalkabilityCoefficientsF32),
 -#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	mA(pOther.mA),
 -	mB(pOther.mB),
 -	mC(pOther.mC),
 -	mD(pOther.mD)
 -{
 -}
 -
 -PathfindingLinkset::~PathfindingLinkset()
 -{
 -}
 -
 -PathfindingLinkset& PathfindingLinkset::operator =(const PathfindingLinkset& pOther)
 -{
 -	mUUID = pOther.mUUID;
 -	mName = pOther.mName;
 -	mDescription = pOther.mDescription;
 -	mLandImpact = pOther.mLandImpact;
 -	mLocation = pOther.mLocation;
 -	mPathState = pOther.mPathState;
 -	mIsPhantom = pOther.mIsPhantom;
 -#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	mIsWalkabilityCoefficientsF32 = pOther.mIsWalkabilityCoefficientsF32;
 -#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	mA = pOther.mA;
 -	mB = pOther.mB;
 -	mC = pOther.mC;
 -	mD = pOther.mD;
 -
 -	return *this;
 -}
 -
 -const LLUUID& PathfindingLinkset::getUUID() const
 -{
 -	return mUUID;
 -}
 -
 -const std::string& PathfindingLinkset::getName() const
 -{
 -	return mName;
 -}
 -
 -const std::string& PathfindingLinkset::getDescription() const
 -{
 -	return mDescription;
 -}
 -
 -U32 PathfindingLinkset::getLandImpact() const
 -{
 -	return mLandImpact;
 -}
 -
 -const LLVector3& PathfindingLinkset::getPositionAgent() const
 -{
 -	return mLocation;
 -}
 -
 -PathfindingLinkset::EPathState PathfindingLinkset::getPathState() const
 -{
 -	return mPathState;
 -}
 -
 -void PathfindingLinkset::setPathState(EPathState pPathState)
 -{
 -	mPathState = pPathState;
 -}
 -
 -PathfindingLinkset::EPathState PathfindingLinkset::getPathState(bool pIsPermanent, bool pIsWalkable)
 -{
 -	return (pIsPermanent ? (pIsWalkable ? kWalkable : kObstacle) : kIgnored);
 -}
 -
 -BOOL PathfindingLinkset::isPermanent(EPathState pPathState)
 -{
 -	BOOL retVal;
 -
 -	switch (pPathState)
 -	{
 -	case kWalkable :
 -	case kObstacle :
 -		retVal = true;
 -		break;
 -	case kIgnored :
 -		retVal = false;
 -		break;
 -	default :
 -		retVal = false;
 -		llassert(0);
 -		break;
 -	}
 -
 -	return retVal;
 -}
 -
 -BOOL PathfindingLinkset::isWalkable(EPathState pPathState)
 -{
 -	BOOL retVal;
 -
 -	switch (pPathState)
 -	{
 -	case kWalkable :
 -		retVal = true;
 -		break;
 -	case kObstacle :
 -	case kIgnored :
 -		retVal = false;
 -		break;
 -	default :
 -		retVal = false;
 -		llassert(0);
 -		break;
 -	}
 -
 -	return retVal;
 -}
 -
 -BOOL PathfindingLinkset::isPhantom() const
 -{
 -	return mIsPhantom;
 -}
 -
 -void PathfindingLinkset::setPhantom(BOOL pIsPhantom)
 -{
 -	mIsPhantom = pIsPhantom;
 -}
 -
 -S32 PathfindingLinkset::getA() const
 -{
 -	return mA;
 -}
 -
 -void PathfindingLinkset::setA(S32 pA)
 -{
 -	mA = pA;
 -}
 -
 -S32 PathfindingLinkset::getB() const
 -{
 -	return mB;
 -}
 -
 -void PathfindingLinkset::setB(S32 pB)
 -{
 -	mB = pB;
 -}
 -
 -S32 PathfindingLinkset::getC() const
 -{
 -	return mC;
 -}
 -
 -void PathfindingLinkset::setC(S32 pC)
 -{
 -	mC = pC;
 -}
 -
 -S32 PathfindingLinkset::getD() const
 -{
 -	return mD;
 -}
 -
 -void PathfindingLinkset::setD(S32 pD)
 -{
 -	mD = pD;
 -}
 -
 -LLSD PathfindingLinkset::getAlteredFields(EPathState pPathState, S32 pA, S32 pB, S32 pC, S32 pD, BOOL pIsPhantom) const
 -{
 -	LLSD itemData;
 -
 -	if (mPathState != pPathState)
 -	{
 -		itemData["permanent"] = static_cast<bool>(PathfindingLinkset::isPermanent(pPathState));
 -		itemData["walkable"] = static_cast<bool>(PathfindingLinkset::isWalkable(pPathState));
 -	}
 -#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	if (mIsWalkabilityCoefficientsF32)
 -	{
 -		if (mA != pA)
 -		{
 -			itemData["A"] = llclamp(static_cast<F32>(pA) / 100.0f, 0.0f, 1.0f);
 -		}
 -		if (mB != pB)
 -		{
 -			itemData["B"] = llclamp(static_cast<F32>(pB) / 100.0f, 0.0f, 1.0f);
 -		}
 -		if (mC != pC)
 -		{
 -			itemData["C"] = llclamp(static_cast<F32>(pC) / 100.0f, 0.0f, 1.0f);
 -		}
 -		if (mD != pD)
 -		{
 -			itemData["D"] = llclamp(static_cast<F32>(pD) / 100.0f, 0.0f, 1.0f);
 -		}
 -	}
 -	else
 -	{
 -		if (mA != pA)
 -		{
 -			itemData["A"] = llclamp(pA, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 -		}
 -		if (mB != pB)
 -		{
 -			itemData["B"] = llclamp(pB, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 -		}
 -		if (mC != pC)
 -		{
 -			itemData["C"] = llclamp(pC, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 -		}
 -		if (mD != pD)
 -		{
 -			itemData["D"] = llclamp(pD, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 -		}
 -	}
 -#else // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	if (mA != pA)
 -	{
 -		itemData["A"] = llclamp(pA, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 -	}
 -	if (mB != pB)
 -	{
 -		itemData["B"] = llclamp(pB, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 -	}
 -	if (mC != pC)
 -	{
 -		itemData["C"] = llclamp(pC, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 -	}
 -	if (mD != pD)
 -	{
 -		itemData["D"] = llclamp(pD, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 -	}
 -#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	if (mIsPhantom != pIsPhantom)
 -	{
 -		itemData["phantom"] = static_cast<bool>(pIsPhantom);
 -	}
 -
 -	return itemData;
 -}
 -
 -//---------------------------------------------------------------------------
 -// FilterString
 -//---------------------------------------------------------------------------
 -
 -FilterString::FilterString()
 -	: mFilter(),
 -	mUpperFilter()
 -{
 -}
 -
 -FilterString::FilterString(const std::string& pFilter)
 -	: mFilter(pFilter),
 -	mUpperFilter()
 -{
 -	LLStringUtil::trim(mFilter);
 -	mUpperFilter = mFilter;
 -	if (!mUpperFilter.empty())
 -	{
 -		LLStringUtil::toUpper(mUpperFilter);
 -	}
 -}
 -
 -FilterString::FilterString(const FilterString& pOther)
 -	: mFilter(pOther.mFilter),
 -	mUpperFilter(pOther.mUpperFilter)
 -{
 -}
 -
 -FilterString::~FilterString()
 -{
 -}
 -
 -const std::string& FilterString::get() const
 -{
 -	return mFilter;
 -}
 -
 -bool FilterString::set(const std::string& pFilter)
 -{
 -	std::string newFilter(pFilter);
 -	LLStringUtil::trim(newFilter);
 -	bool didFilterChange = (mFilter.compare(newFilter) != 0);
 -	if (didFilterChange)
 -	{
 -		mFilter = newFilter;
 -		mUpperFilter = newFilter;
 -		LLStringUtil::toUpper(mUpperFilter);
 -	}
 -
 -	return didFilterChange;
 -}
 -
 -void FilterString::clear()
 -{
 -	mFilter.clear();
 -	mUpperFilter.clear();
 -}
 -
 -bool FilterString::isActive() const
 -{
 -	return !mFilter.empty();
 -}
 -
 -bool FilterString::doesMatch(const std::string& pTestString) const
 -{
 -	bool doesMatch = true;
 -
 -	if (isActive())
 -	{
 -		std::string upperTestString(pTestString);
 -		LLStringUtil::toUpper(upperTestString);
 -		doesMatch = (upperTestString.find(mUpperFilter) != std::string::npos);
 -	}
 -
 -	return doesMatch;
 -}
 -
 -//---------------------------------------------------------------------------
 -// PathfindingLinksets
 -//---------------------------------------------------------------------------
 -
 -PathfindingLinksets::PathfindingLinksets()
 -	: mAllLinksets(),
 -	mFilteredLinksets(),
 -	mIsFiltersDirty(false),
 -	mNameFilter(),
 -	mDescriptionFilter(),
 -	mIsWalkableFilter(true),
 -	mIsObstacleFilter(true),
 -	mIsIgnoredFilter(true)
 -{
 -}
 -
 -PathfindingLinksets::PathfindingLinksets(const LLSD& pNavMeshData)
 -	: mAllLinksets(),
 -	mFilteredLinksets(),
 -	mIsFiltersDirty(false),
 -	mNameFilter(),
 -	mDescriptionFilter(),
 -	mIsWalkableFilter(true),
 -	mIsObstacleFilter(true),
 -	mIsIgnoredFilter(true)
 -{
 -	setNavMeshData(pNavMeshData);
 -}
 -
 -PathfindingLinksets::PathfindingLinksets(const PathfindingLinksets& pOther)
 -	: mAllLinksets(pOther.mAllLinksets),
 -	mFilteredLinksets(pOther.mFilteredLinksets),
 -	mIsFiltersDirty(pOther.mIsFiltersDirty),
 -	mNameFilter(pOther.mNameFilter),
 -	mDescriptionFilter(pOther.mDescriptionFilter),
 -	mIsWalkableFilter(pOther.mIsWalkableFilter),
 -	mIsObstacleFilter(pOther.mIsObstacleFilter),
 -	mIsIgnoredFilter(pOther.mIsIgnoredFilter)
 -{
 -}
 -
 -PathfindingLinksets::~PathfindingLinksets()
 -{
 -	clearLinksets();
 -}
 -
 -void PathfindingLinksets::setNavMeshData(const LLSD& pNavMeshData)
 -{
 -	clearLinksets();
 -
 -	for (LLSD::map_const_iterator navMeshDataIter = pNavMeshData.beginMap();
 -		navMeshDataIter != pNavMeshData.endMap(); ++navMeshDataIter)
 -	{
 -		const std::string& uuid(navMeshDataIter->first);
 -		const LLSD& linksetData = navMeshDataIter->second;
 -		PathfindingLinkset linkset(uuid, linksetData);
 -
 -		mAllLinksets.insert(std::pair<std::string, PathfindingLinkset>(uuid, linkset));
 -	}
 -
 -	mIsFiltersDirty = true;
 -}
 -
 -void PathfindingLinksets::updateNavMeshData(const LLSD& pNavMeshData)
 -{
 -	for (LLSD::map_const_iterator navMeshDataIter = pNavMeshData.beginMap();
 -		navMeshDataIter != pNavMeshData.endMap(); ++navMeshDataIter)
 -	{
 -		const std::string& uuid(navMeshDataIter->first);
 -		const LLSD& linksetData = navMeshDataIter->second;
 -		PathfindingLinkset linkset(uuid, linksetData);
 -
 -		PathfindingLinksetMap::iterator linksetIter = mAllLinksets.find(uuid);
 -		if (linksetIter == mAllLinksets.end())
 -		{
 -			mAllLinksets.insert(std::pair<std::string, PathfindingLinkset>(uuid, linkset));
 -		}
 -		else
 -		{
 -			linksetIter->second = linkset;
 -		}
 -	}
 -
 -	mIsFiltersDirty = true;
 -}
 -
 -void PathfindingLinksets::clearLinksets()
 -{
 -	mAllLinksets.clear();
 -	mFilteredLinksets.clear();
 -	mIsFiltersDirty = false;
 -}
 -
 -const PathfindingLinksets::PathfindingLinksetMap& PathfindingLinksets::getAllLinksets() const
 -{
 -	return mAllLinksets;
 -}
 -
 -const PathfindingLinksets::PathfindingLinksetMap& PathfindingLinksets::getFilteredLinksets()
 -{
 -	if (!isFiltersActive())
 -	{
 -		return mAllLinksets;
 -	}
 -	else
 -	{
 -		applyFilters();
 -		return mFilteredLinksets;
 -	}
 -}
 -
 -BOOL PathfindingLinksets::isFiltersActive() const
 -{
 -	return (mNameFilter.isActive() || mDescriptionFilter.isActive() || !mIsWalkableFilter || !mIsObstacleFilter || !mIsIgnoredFilter);
 -}
 -
 -void PathfindingLinksets::setNameFilter(const std::string& pNameFilter)
 -{
 -	mIsFiltersDirty = (mNameFilter.set(pNameFilter) || mIsFiltersDirty);
 -}
 -
 -const std::string& PathfindingLinksets::getNameFilter() const
 -{
 -	return mNameFilter.get();
 -}
 -
 -void PathfindingLinksets::setDescriptionFilter(const std::string& pDescriptionFilter)
 -{
 -	mIsFiltersDirty = (mDescriptionFilter.set(pDescriptionFilter) || mIsFiltersDirty);
 -}
 -
 -const std::string& PathfindingLinksets::getDescriptionFilter() const
 -{
 -	return mDescriptionFilter.get();
 -}
 -
 -void PathfindingLinksets::setWalkableFilter(BOOL pWalkableFilter)
 -{
 -	mIsFiltersDirty = (mIsFiltersDirty || (mIsWalkableFilter == pWalkableFilter));
 -	mIsWalkableFilter = pWalkableFilter;
 -}
 -
 -BOOL PathfindingLinksets::isWalkableFilter() const
 -{
 -	return mIsWalkableFilter;
 -}
 -
 -void PathfindingLinksets::setObstacleFilter(BOOL pObstacleFilter)
 -{
 -	mIsFiltersDirty = (mIsFiltersDirty || (mIsObstacleFilter == pObstacleFilter));
 -	mIsObstacleFilter = pObstacleFilter;
 -}
 -
 -BOOL PathfindingLinksets::isObstacleFilter() const
 -{
 -	return mIsObstacleFilter;
 -}
 -
 -void PathfindingLinksets::setIgnoredFilter(BOOL pIgnoredFilter)
 -{
 -	mIsFiltersDirty = (mIsFiltersDirty || (mIsIgnoredFilter == pIgnoredFilter));
 -	mIsIgnoredFilter = pIgnoredFilter;
 -}
 -
 -BOOL PathfindingLinksets::isIgnoredFilter() const
 -{
 -	return mIsIgnoredFilter;
 -}
 -
 -void PathfindingLinksets::clearFilters()
 -{
 -	mNameFilter.clear();
 -	mDescriptionFilter.clear();
 -	mIsWalkableFilter = true;
 -	mIsObstacleFilter = true;
 -	mIsIgnoredFilter = true;
 -	mIsFiltersDirty = false;
 -}
 -
 -void PathfindingLinksets::applyFilters()
 -{
 -	mFilteredLinksets.clear();
 -
 -	for (PathfindingLinksetMap::const_iterator linksetIter = mAllLinksets.begin();
 -		linksetIter != mAllLinksets.end(); ++linksetIter)
 -	{
 -		const std::string& uuid(linksetIter->first);
 -		const PathfindingLinkset& linkset(linksetIter->second);
 -		if (doesMatchFilters(linkset))
 -		{
 -			mFilteredLinksets.insert(std::pair<std::string, PathfindingLinkset>(uuid, linkset));
 -		}
 -	}
 -
 -	mIsFiltersDirty = false;
 -}
 -
 -BOOL PathfindingLinksets::doesMatchFilters(const PathfindingLinkset& pLinkset) const
 -{
 -	return (((mIsWalkableFilter && (pLinkset.getPathState() == PathfindingLinkset::kWalkable)) ||
 -			 (mIsObstacleFilter && (pLinkset.getPathState() == PathfindingLinkset::kObstacle)) ||
 -			 (mIsIgnoredFilter && (pLinkset.getPathState() == PathfindingLinkset::kIgnored))) &&
 -			(!mNameFilter.isActive() || mNameFilter.doesMatch(pLinkset.getName())) &&
 -			(!mDescriptionFilter.isActive() || mDescriptionFilter.doesMatch(pLinkset.getDescription())));
 -}
 -
 -//---------------------------------------------------------------------------
  // LLFloaterPathfindingLinksets
  //---------------------------------------------------------------------------
 @@ -889,6 +234,7 @@ BOOL LLFloaterPathfindingLinksets::isMessagingInProgress() const  LLFloaterPathfindingLinksets::LLFloaterPathfindingLinksets(const LLSD& pSeed)
  	: LLFloater(pSeed),
 +	mSelfHandle(),
  	mPathfindingLinksets(),
  	mMessagingState(kMessagingInitial),
  	mLinksetsScrollList(NULL),
 @@ -914,6 +260,7 @@ LLFloaterPathfindingLinksets::LLFloaterPathfindingLinksets(const LLSD& pSeed)  	mEditPhantom(NULL),
  	mApplyEdits(NULL)
  {
 +	mSelfHandle.bind(this);
  }
  LLFloaterPathfindingLinksets::~LLFloaterPathfindingLinksets()
 @@ -932,7 +279,7 @@ void LLFloaterPathfindingLinksets::sendNavMeshDataGetRequest()  	else
  	{
  		setMessagingState(kMessagingFetchStarting);
 -		mPathfindingLinksets.clearLinksets();
 +		mPathfindingLinksets.clearPathfindingLinksets();
  		updateLinksetsList();
  		std::string navMeshDataURL = getCapabilityURL();
 @@ -944,7 +291,7 @@ void LLFloaterPathfindingLinksets::sendNavMeshDataGetRequest()  		else
  		{
  			setMessagingState(kMessagingFetchRequestSent);
 -			LLHTTPClient::get(navMeshDataURL, new NavMeshDataGetResponder(navMeshDataURL, this));
 +			LLHTTPClient::get(navMeshDataURL, new NavMeshDataGetResponder(navMeshDataURL, mSelfHandle));
  		}
  	}
  }
 @@ -960,7 +307,7 @@ void LLFloaterPathfindingLinksets::sendNavMeshDataPutRequest(const LLSD& pPostDa  		}
  		else
  		{
 -			LLHTTPClient::put(navMeshDataURL, pPostData, new NavMeshDataPutResponder(navMeshDataURL, this));
 +			LLHTTPClient::put(navMeshDataURL, pPostData, new NavMeshDataPutResponder(navMeshDataURL, mSelfHandle));
  		}
  	}
  }
 @@ -968,7 +315,7 @@ void LLFloaterPathfindingLinksets::sendNavMeshDataPutRequest(const LLSD& pPostDa  void LLFloaterPathfindingLinksets::handleNavMeshDataGetReply(const LLSD& pNavMeshData)
  {
  	setMessagingState(kMessagingFetchReceived);
 -	mPathfindingLinksets.setNavMeshData(pNavMeshData);
 +	mPathfindingLinksets.setPathfindingLinksets(pNavMeshData);
  	updateLinksetsList();
  	setMessagingState(kMessagingComplete);
  }
 @@ -976,7 +323,7 @@ void LLFloaterPathfindingLinksets::handleNavMeshDataGetReply(const LLSD& pNavMes  void LLFloaterPathfindingLinksets::handleNavMeshDataGetError(const std::string& pURL, const std::string& pErrorReason)
  {
  	setMessagingState(kMessagingFetchError);
 -	mPathfindingLinksets.clearLinksets();
 +	mPathfindingLinksets.clearPathfindingLinksets();
  	updateLinksetsList();
  	llwarns << "Error fetching object navmesh properties from URL '" << pURL << "' because " << pErrorReason << llendl;
  }
 @@ -984,7 +331,7 @@ void LLFloaterPathfindingLinksets::handleNavMeshDataGetError(const std::string&  void LLFloaterPathfindingLinksets::handleNavMeshDataPutReply(const LLSD& pModifiedData)
  {
  	setMessagingState(kMessagingModifyReceived);
 -	mPathfindingLinksets.updateNavMeshData(pModifiedData);
 +	mPathfindingLinksets.updatePathfindingLinksets(pModifiedData);
  	updateLinksetsList();
  	setMessagingState(kMessagingComplete);
  }
 @@ -1025,6 +372,7 @@ void LLFloaterPathfindingLinksets::setMessagingState(EMessagingState pMessagingS  {
  	mMessagingState = pMessagingState;
  	updateLinksetsStatusMessage();
 +	updateEditFields();
  }
  void LLFloaterPathfindingLinksets::onApplyFiltersClicked()
 @@ -1104,12 +452,12 @@ void LLFloaterPathfindingLinksets::updateLinksetsList()  	updateLinksetsStatusMessage();
  	const LLVector3& avatarPosition = gAgent.getPositionAgent();
 -	const PathfindingLinksets::PathfindingLinksetMap& linksetMap = mPathfindingLinksets.getFilteredLinksets();
 +	const LLFilteredPathfindingLinksets::PathfindingLinksetMap& linksetMap = mPathfindingLinksets.getFilteredLinksets();
 -	for (PathfindingLinksets::PathfindingLinksetMap::const_iterator linksetIter = linksetMap.begin();
 +	for (LLFilteredPathfindingLinksets::PathfindingLinksetMap::const_iterator linksetIter = linksetMap.begin();
  		linksetIter != linksetMap.end(); ++linksetIter)
  	{
 -		const PathfindingLinkset& linkset(linksetIter->second);
 +		const LLPathfindingLinkset& linkset(linksetIter->second);
  		LLSD columns;
 @@ -1126,19 +474,19 @@ void LLFloaterPathfindingLinksets::updateLinksetsList()  		columns[2]["font"] = "SANSSERIF";
  		columns[3]["column"] = "dist_from_you";
 -		columns[3]["value"] = llformat("%1.0f m", dist_vec(avatarPosition, linkset.getPositionAgent()));
 +		columns[3]["value"] = llformat("%1.0f m", dist_vec(avatarPosition, linkset.getLocation()));
  		columns[3]["font"] = "SANSSERIF";
  		columns[4]["column"] = "path_state";
  		switch (linkset.getPathState())
  		{
 -		case PathfindingLinkset::kWalkable :
 +		case LLPathfindingLinkset::kWalkable :
  			columns[4]["value"] = getString("linkset_path_state_walkable");
  			break;
 -		case PathfindingLinkset::kObstacle :
 +		case LLPathfindingLinkset::kObstacle :
  			columns[4]["value"] = getString("linkset_path_state_obstacle");
  			break;
 -		case PathfindingLinkset::kIgnored :
 +		case LLPathfindingLinkset::kIgnored :
  			columns[4]["value"] = getString("linkset_path_state_ignored");
  			break;
  		default :
 @@ -1153,19 +501,19 @@ void LLFloaterPathfindingLinksets::updateLinksetsList()  		columns[5]["font"] = "SANSSERIF";
  		columns[6]["column"] = "a_percent";
 -		columns[6]["value"] = llformat("%3d", linkset.getA());
 +		columns[6]["value"] = llformat("%3d", linkset.getWalkabilityCoefficientA());
  		columns[6]["font"] = "SANSSERIF";
  		columns[7]["column"] = "b_percent";
 -		columns[7]["value"] = llformat("%3d", linkset.getB());
 +		columns[7]["value"] = llformat("%3d", linkset.getWalkabilityCoefficientB());
  		columns[7]["font"] = "SANSSERIF";
  		columns[8]["column"] = "c_percent";
 -		columns[8]["value"] = llformat("%3d", linkset.getC());
 +		columns[8]["value"] = llformat("%3d", linkset.getWalkabilityCoefficientC());
  		columns[8]["font"] = "SANSSERIF";
  		columns[9]["column"] = "d_percent";
 -		columns[9]["value"] = llformat("%3d", linkset.getD());
 +		columns[9]["value"] = llformat("%3d", linkset.getWalkabilityCoefficientD());
  		columns[9]["font"] = "SANSSERIF";
  		LLSD element;
 @@ -1177,6 +525,7 @@ void LLFloaterPathfindingLinksets::updateLinksetsList()  	mLinksetsScrollList->selectMultiple(selectedUUIDs);
  	updateLinksetsStatusMessage();
 +	updateEditFields();
  }
  void LLFloaterPathfindingLinksets::selectAllLinksets()
 @@ -1280,15 +629,15 @@ void LLFloaterPathfindingLinksets::updateEditFields()  	{
  		LLScrollListItem *firstItem = selectedItems.front();
 -		const PathfindingLinksets::PathfindingLinksetMap &linksetsMap = mPathfindingLinksets.getAllLinksets();
 -		PathfindingLinksets::PathfindingLinksetMap::const_iterator linksetIter = linksetsMap.find(firstItem->getUUID().asString());
 -		const PathfindingLinkset &linkset(linksetIter->second);
 +		const LLFilteredPathfindingLinksets::PathfindingLinksetMap &linksetsMap = mPathfindingLinksets.getAllLinksets();
 +		LLFilteredPathfindingLinksets::PathfindingLinksetMap::const_iterator linksetIter = linksetsMap.find(firstItem->getUUID().asString());
 +		const LLPathfindingLinkset &linkset(linksetIter->second);
  		setPathState(linkset.getPathState());
 -		mEditA->setValue(LLSD(linkset.getA()));
 -		mEditB->setValue(LLSD(linkset.getB()));
 -		mEditC->setValue(LLSD(linkset.getC()));
 -		mEditD->setValue(LLSD(linkset.getD()));
 +		mEditA->setValue(LLSD(linkset.getWalkabilityCoefficientA()));
 +		mEditB->setValue(LLSD(linkset.getWalkabilityCoefficientB()));
 +		mEditC->setValue(LLSD(linkset.getWalkabilityCoefficientC()));
 +		mEditD->setValue(LLSD(linkset.getWalkabilityCoefficientD()));
  		mEditPhantom->set(linkset.isPhantom());
  		setEnableEditFields(true);
 @@ -1300,7 +649,7 @@ void LLFloaterPathfindingLinksets::applyEditFields()  	std::vector<LLScrollListItem*> selectedItems = mLinksetsScrollList->getAllSelected();
  	if (!selectedItems.empty())
  	{
 -		PathfindingLinkset::EPathState pathState = getPathState();
 +		LLPathfindingLinkset::EPathState pathState = getPathState();
  		const std::string &aString = mEditA->getText();
  		const std::string &bString = mEditB->getText();
  		const std::string &cString = mEditC->getText();
 @@ -1311,7 +660,7 @@ void LLFloaterPathfindingLinksets::applyEditFields()  		S32 dValue = static_cast<S32>(atoi(dString.c_str()));
  		BOOL isPhantom = mEditPhantom->getValue();
 -		const PathfindingLinksets::PathfindingLinksetMap &linksetsMap = mPathfindingLinksets.getAllLinksets();
 +		const LLFilteredPathfindingLinksets::PathfindingLinksetMap &linksetsMap = mPathfindingLinksets.getAllLinksets();
  		LLSD editData;
  		for (std::vector<LLScrollListItem*>::const_iterator itemIter = selectedItems.begin();
 @@ -1320,10 +669,10 @@ void LLFloaterPathfindingLinksets::applyEditFields()  			const LLScrollListItem *listItem = *itemIter;
  			LLUUID uuid = listItem->getUUID();
 -			const PathfindingLinksets::PathfindingLinksetMap::const_iterator linksetIter = linksetsMap.find(uuid.asString());
 -			const PathfindingLinkset &linkset = linksetIter->second;
 +			const LLFilteredPathfindingLinksets::PathfindingLinksetMap::const_iterator linksetIter = linksetsMap.find(uuid.asString());
 +			const LLPathfindingLinkset &linkset = linksetIter->second;
 -			LLSD itemData = linkset.getAlteredFields(pathState, aValue, bValue, cValue, dValue, isPhantom);
 +			LLSD itemData = linkset.encodeAlteredFields(pathState, aValue, bValue, cValue, dValue, isPhantom);
  			if (!itemData.isUndefined())
  			{
 @@ -1361,23 +710,23 @@ void LLFloaterPathfindingLinksets::setEnableEditFields(BOOL pEnabled)  	mApplyEdits->setEnabled(pEnabled);
  }
 -PathfindingLinkset::EPathState LLFloaterPathfindingLinksets::getPathState() const
 +LLPathfindingLinkset::EPathState LLFloaterPathfindingLinksets::getPathState() const
  {
 -	PathfindingLinkset::EPathState pathState;
 +	LLPathfindingLinkset::EPathState pathState;
  	switch (mEditPathState->getValue().asInteger())
  	{
  	case XUI_PATH_STATE_WALKABLE :
 -		pathState = PathfindingLinkset::kWalkable;
 +		pathState = LLPathfindingLinkset::kWalkable;
  		break;
  	case XUI_PATH_STATE_OBSTACLE :
 -		pathState = PathfindingLinkset::kObstacle;
 +		pathState = LLPathfindingLinkset::kObstacle;
  		break;
  	case XUI_PATH_STATE_IGNORED :
 -		pathState = PathfindingLinkset::kIgnored;
 +		pathState = LLPathfindingLinkset::kIgnored;
  		break;
  	default :
 -		pathState = PathfindingLinkset::kIgnored;
 +		pathState = LLPathfindingLinkset::kIgnored;
  		llassert(0);
  		break;
  	}
 @@ -1385,19 +734,19 @@ PathfindingLinkset::EPathState LLFloaterPathfindingLinksets::getPathState() cons  	return pathState;
  }
 -void LLFloaterPathfindingLinksets::setPathState(PathfindingLinkset::EPathState pPathState)
 +void LLFloaterPathfindingLinksets::setPathState(LLPathfindingLinkset::EPathState pPathState)
  {
  	LLSD radioGroupValue;
  	switch (pPathState)
  	{
 -	case PathfindingLinkset::kWalkable :
 +	case LLPathfindingLinkset::kWalkable :
  		radioGroupValue = XUI_PATH_STATE_WALKABLE;
  		break;
 -	case PathfindingLinkset::kObstacle :
 +	case LLPathfindingLinkset::kObstacle :
  		radioGroupValue = XUI_PATH_STATE_OBSTACLE;
  		break;
 -	case PathfindingLinkset::kIgnored :
 +	case LLPathfindingLinkset::kIgnored :
  		radioGroupValue = XUI_PATH_STATE_IGNORED;
  		break;
  	default :
 @@ -1413,48 +762,64 @@ void LLFloaterPathfindingLinksets::setPathState(PathfindingLinkset::EPathState p  // NavMeshDataGetResponder
  //---------------------------------------------------------------------------
 -NavMeshDataGetResponder::NavMeshDataGetResponder(const std::string& pNavMeshDataGetURL, LLFloaterPathfindingLinksets *pLinksetsFloater)
 +NavMeshDataGetResponder::NavMeshDataGetResponder(const std::string& pNavMeshDataGetURL,
 +	const LLHandle<LLFloaterPathfindingLinksets> &pLinksetsHandle)
  	: mNavMeshDataGetURL(pNavMeshDataGetURL),
 -	mLinksetsFloater(pLinksetsFloater)
 +	mLinksetsFloaterHandle(pLinksetsHandle)
  {
  }
  NavMeshDataGetResponder::~NavMeshDataGetResponder()
  {
 -	mLinksetsFloater = NULL;
  }
  void NavMeshDataGetResponder::result(const LLSD& pContent)
  {
 -	mLinksetsFloater->handleNavMeshDataGetReply(pContent);
 +	LLFloaterPathfindingLinksets *linksetsFloater = mLinksetsFloaterHandle.get();
 +	if (linksetsFloater != NULL)
 +	{
 +		linksetsFloater->handleNavMeshDataGetReply(pContent);
 +	}
  }
  void NavMeshDataGetResponder::error(U32 status, const std::string& reason)
  {
 -	mLinksetsFloater->handleNavMeshDataGetError(mNavMeshDataGetURL, reason);
 +	LLFloaterPathfindingLinksets *linksetsFloater = mLinksetsFloaterHandle.get();
 +	if (linksetsFloater != NULL)
 +	{
 +		linksetsFloater->handleNavMeshDataGetError(mNavMeshDataGetURL, reason);
 +	}
  }
  //---------------------------------------------------------------------------
  // NavMeshDataPutResponder
  //---------------------------------------------------------------------------
 -NavMeshDataPutResponder::NavMeshDataPutResponder(const std::string& pNavMeshDataPutURL, LLFloaterPathfindingLinksets *pLinksetsFloater)
 +NavMeshDataPutResponder::NavMeshDataPutResponder(const std::string& pNavMeshDataPutURL,
 +	const LLHandle<LLFloaterPathfindingLinksets> &pLinksetsHandle)
  	: mNavMeshDataPutURL(pNavMeshDataPutURL),
 -	mLinksetsFloater(pLinksetsFloater)
 +	mLinksetsFloaterHandle(pLinksetsHandle)
  {
  }
  NavMeshDataPutResponder::~NavMeshDataPutResponder()
  {
 -	mLinksetsFloater = NULL;
  }
  void NavMeshDataPutResponder::result(const LLSD& pContent)
  {
 -	mLinksetsFloater->handleNavMeshDataPutReply(pContent);
 +	LLFloaterPathfindingLinksets *linksetsFloater = mLinksetsFloaterHandle.get();
 +	if (linksetsFloater != NULL)
 +	{
 +		linksetsFloater->handleNavMeshDataPutReply(pContent);
 +	}
  }
  void NavMeshDataPutResponder::error(U32 status, const std::string& reason)
  {
 -	mLinksetsFloater->handleNavMeshDataPutError(mNavMeshDataPutURL, reason);
 +	LLFloaterPathfindingLinksets *linksetsFloater = mLinksetsFloaterHandle.get();
 +	if (linksetsFloater != NULL)
 +	{
 +		linksetsFloater->handleNavMeshDataPutError(mNavMeshDataPutURL, reason);
 +	}
  }
 diff --git a/indra/newview/llfloaterpathfindinglinksets.h b/indra/newview/llfloaterpathfindinglinksets.h index 976eaa355f..250625c72a 100644 --- a/indra/newview/llfloaterpathfindinglinksets.h +++ b/indra/newview/llfloaterpathfindinglinksets.h @@ -28,15 +28,13 @@  #ifndef LL_LLFLOATERPATHFINDINGLINKSETS_H
  #define LL_LLFLOATERPATHFINDINGLINKSETS_H
 -#include "llsd.h"
 -#include "v3math.h"
 +#include "llhandle.h"
  #include "llfloater.h"
  #include "lluuid.h"
 +#include "llpathfindinglinkset.h"
 +#include "llfilteredpathfindinglinksets.h"
 -// This is a reminder to remove the code regarding the changing of the data type for the
 -// walkability coefficients from F32 to S32 representing the percentage from 0-100.
 -#define XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -
 +class LLSD;
  class LLTextBase;
  class LLScrollListCtrl;
  class LLLineEditor;
 @@ -44,142 +42,6 @@ class LLCheckBoxCtrl;  class LLRadioGroup;
  class LLButton;
 -class PathfindingLinkset
 -{
 -public:
 -	typedef enum
 -	{
 -		kWalkable,
 -		kObstacle,
 -		kIgnored
 -	} EPathState;
 -
 -	PathfindingLinkset(const std::string &pUUID, const LLSD &pNavMeshItem);
 -	PathfindingLinkset(const PathfindingLinkset& pOther);
 -	virtual ~PathfindingLinkset();
 -
 -	PathfindingLinkset& operator = (const PathfindingLinkset& pOther);
 -
 -	const LLUUID&      getUUID() const;
 -	const std::string& getName() const;
 -	const std::string& getDescription() const;
 -	U32                getLandImpact() const;
 -	const LLVector3&   getPositionAgent() const;
 -
 -	EPathState         getPathState() const;
 -	void               setPathState(EPathState pPathState);
 -	static EPathState  getPathState(bool pIsPermanent, bool pIsWalkable);
 -	static BOOL        isPermanent(EPathState pPathState);
 -	static BOOL        isWalkable(EPathState pPathState);
 -
 -	BOOL               isPhantom() const;
 -	void               setPhantom(BOOL pIsPhantom);
 -
 -	S32                getA() const;
 -	void               setA(S32 pA);
 -
 -	S32                getB() const;
 -	void               setB(S32 pB);
 -
 -	S32                getC() const;
 -	void               setC(S32 pC);
 -
 -	S32                getD() const;
 -	void               setD(S32 pD);
 -
 -	LLSD               getAlteredFields(EPathState pPathState, S32 pA, S32 pB, S32 pC, S32 pD, BOOL pIsPhantom) const;
 -
 -protected:
 -
 -private:
 -	static const S32 MIN_WALKABILITY_VALUE;
 -	static const S32 MAX_WALKABILITY_VALUE;
 -
 -	LLUUID      mUUID;
 -	std::string mName;
 -	std::string mDescription;
 -	U32         mLandImpact;
 -	LLVector3   mLocation;
 -	EPathState  mPathState;
 -	BOOL        mIsPhantom;
 -#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	BOOL        mIsWalkabilityCoefficientsF32;
 -#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 -	S32         mA;
 -	S32         mB;
 -	S32         mC;
 -	S32         mD;
 -};
 -
 -class FilterString
 -{
 -public:
 -	FilterString();
 -	FilterString(const std::string& pFilter);
 -	FilterString(const FilterString& pOther);
 -	virtual ~FilterString();
 -
 -	const std::string& get() const;
 -	bool               set(const std::string& pFilter);
 -	void               clear();
 -
 -	bool isActive() const;
 -	bool doesMatch(const std::string& pTestString) const;
 -
 -protected:
 -
 -private:
 -	std::string mFilter;
 -	std::string mUpperFilter;
 -};
 -
 -class PathfindingLinksets
 -{
 -public:
 -	typedef std::map<std::string, PathfindingLinkset> PathfindingLinksetMap;
 -
 -	PathfindingLinksets();
 -	PathfindingLinksets(const LLSD& pNavMeshData);
 -	PathfindingLinksets(const PathfindingLinksets& pOther);
 -	virtual ~PathfindingLinksets();
 -
 -	void setNavMeshData(const LLSD& pNavMeshData);
 -	void updateNavMeshData(const LLSD& pNavMeshData);
 -	void clearLinksets();
 -
 -	const PathfindingLinksetMap& getAllLinksets() const;
 -	const PathfindingLinksetMap& getFilteredLinksets();
 -
 -	BOOL               isFiltersActive() const;
 -	void               setNameFilter(const std::string& pNameFilter);
 -	const std::string& getNameFilter() const;
 -	void               setDescriptionFilter(const std::string& pDescriptionFilter);
 -	const std::string& getDescriptionFilter() const;
 -	void               setWalkableFilter(BOOL pWalkableFilter);
 -	BOOL               isWalkableFilter() const;
 -	void               setObstacleFilter(BOOL pObstacleFilter);
 -	BOOL               isObstacleFilter() const;
 -	void               setIgnoredFilter(BOOL pIgnoredFilter);
 -	BOOL               isIgnoredFilter() const;
 -	void               clearFilters();
 -
 -protected:
 -
 -private:
 -	PathfindingLinksetMap mAllLinksets;
 -	PathfindingLinksetMap mFilteredLinksets;
 -
 -	bool         mIsFiltersDirty;
 -	FilterString mNameFilter;
 -	FilterString mDescriptionFilter;
 -	BOOL         mIsWalkableFilter;
 -	BOOL         mIsObstacleFilter;
 -	BOOL         mIsIgnoredFilter;
 -
 -	void applyFilters();
 -	BOOL doesMatchFilters(const PathfindingLinkset& pLinkset) const;
 -};
 -
  class LLFloaterPathfindingLinksets
  :	public LLFloater
  {
 @@ -214,30 +76,31 @@ public:  protected:
  private:
 -	PathfindingLinksets mPathfindingLinksets;
 -	EMessagingState     mMessagingState;
 -	LLScrollListCtrl    *mLinksetsScrollList;
 -	LLTextBase          *mLinksetsStatus;
 -	LLLineEditor        *mFilterByName;
 -	LLLineEditor        *mFilterByDescription;
 -	LLCheckBoxCtrl      *mFilterByWalkable;
 -	LLCheckBoxCtrl      *mFilterByObstacle;
 -	LLCheckBoxCtrl      *mFilterByIgnored;
 -	LLRadioGroup        *mEditPathState;
 -	LLUICtrl            *mEditPathStateWalkable;
 -	LLUICtrl            *mEditPathStateObstacle;
 -	LLUICtrl            *mEditPathStateIgnored;
 -	LLTextBase          *mLabelWalkabilityCoefficients;
 -	LLTextBase          *mLabelEditA;
 -	LLTextBase          *mLabelEditB;
 -	LLTextBase          *mLabelEditC;
 -	LLTextBase          *mLabelEditD;
 -	LLLineEditor        *mEditA;
 -	LLLineEditor        *mEditB;
 -	LLLineEditor        *mEditC;
 -	LLLineEditor        *mEditD;
 -	LLCheckBoxCtrl      *mEditPhantom;
 -	LLButton            *mApplyEdits;
 +	LLRootHandle<LLFloaterPathfindingLinksets> mSelfHandle;
 +	LLFilteredPathfindingLinksets              mPathfindingLinksets;
 +	EMessagingState                            mMessagingState;
 +	LLScrollListCtrl                           *mLinksetsScrollList;
 +	LLTextBase                                 *mLinksetsStatus;
 +	LLLineEditor                               *mFilterByName;
 +	LLLineEditor                               *mFilterByDescription;
 +	LLCheckBoxCtrl                             *mFilterByWalkable;
 +	LLCheckBoxCtrl                             *mFilterByObstacle;
 +	LLCheckBoxCtrl                             *mFilterByIgnored;
 +	LLRadioGroup                               *mEditPathState;
 +	LLUICtrl                                   *mEditPathStateWalkable;
 +	LLUICtrl                                   *mEditPathStateObstacle;
 +	LLUICtrl                                   *mEditPathStateIgnored;
 +	LLTextBase                                 *mLabelWalkabilityCoefficients;
 +	LLTextBase                                 *mLabelEditA;
 +	LLTextBase                                 *mLabelEditB;
 +	LLTextBase                                 *mLabelEditC;
 +	LLTextBase                                 *mLabelEditD;
 +	LLLineEditor                               *mEditA;
 +	LLLineEditor                               *mEditB;
 +	LLLineEditor                               *mEditC;
 +	LLLineEditor                               *mEditD;
 +	LLCheckBoxCtrl                             *mEditPhantom;
 +	LLButton                                   *mApplyEdits;
  	// Does its own instance management, so clients not allowed
  	// to allocate or destroy.
 @@ -277,8 +140,8 @@ private:  	void applyEditFields();
  	void setEnableEditFields(BOOL pEnabled);
 -	PathfindingLinkset::EPathState getPathState() const;
 -	void                           setPathState(PathfindingLinkset::EPathState pPathState);
 +	LLPathfindingLinkset::EPathState getPathState() const;
 +	void                             setPathState(LLPathfindingLinkset::EPathState pPathState);
  };
  #endif // LL_LLFLOATERPATHFINDINGLINKSETS_H
 diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a97e256c89..c64479f589 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -498,9 +498,11 @@ void LLMeshRepoThread::run()  					LODRequest req = mLODReqQ.front();  					mLODReqQ.pop();  					mMutex->unlock(); -					if (fetchMeshLOD(req.mMeshParams, req.mLOD)) +					if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit  					{ -						count++; +						mMutex->lock(); +						mLODReqQ.push(req) ;  +						mMutex->unlock();  					}  				}  			} @@ -512,9 +514,11 @@ void LLMeshRepoThread::run()  					HeaderRequest req = mHeaderReqQ.front();  					mHeaderReqQ.pop();  					mMutex->unlock(); -					if (fetchMeshHeader(req.mMeshParams)) +					if (!fetchMeshHeader(req.mMeshParams, count))//failed, resubmit  					{ -						count++; +						mMutex->lock(); +						mHeaderReqQ.push(req) ; +						mMutex->unlock();  					}  				}  			} @@ -658,6 +662,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  		return false;  	} +	bool ret = true ;  	U32 header_size = mMeshHeaderSize[mesh_id];  	if (header_size > 0) @@ -673,7 +678,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  			//check VFS for mesh skin info  			LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH);  			if (file.getSize() >= offset+size) -			{ +			{				  				LLMeshRepository::sCacheBytesRead += size;  				file.seek(offset);  				U8* buffer = new U8[size]; @@ -689,7 +694,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  				if (!zero)  				{ //attempt to parse  					if (skinInfoReceived(mesh_id, buffer, size)) -					{ +					{						  						delete[] buffer;  						return true;  					} @@ -704,11 +709,14 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{ -				++sActiveLODRequests; -				LLMeshRepository::sHTTPRequestCount++; -				mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, +			{				 +				ret = mCurlRequest->getByteRange(http_url, headers, offset, size,  										   new LLMeshSkinInfoResponder(mesh_id, offset, size)); +				if(ret) +				{ +					++sActiveLODRequests; +					LLMeshRepository::sHTTPRequestCount++; +				}  			}  		}  	} @@ -718,7 +726,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  	}  	//early out was not hit, effectively fetched -	return true; +	return ret;  }  bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) @@ -732,7 +740,8 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  	}  	U32 header_size = mMeshHeaderSize[mesh_id]; - +	bool ret = true ; +	  	if (header_size > 0)  	{  		S32 version = mMeshHeader[mesh_id]["version"].asInteger(); @@ -748,6 +757,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  			if (file.getSize() >= offset+size)  			{  				LLMeshRepository::sCacheBytesRead += size; +  				file.seek(offset);  				U8* buffer = new U8[size];  				file.read(buffer, size); @@ -777,11 +787,14 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{ -				++sActiveLODRequests; -				LLMeshRepository::sHTTPRequestCount++; -				mCurlRequest->getByteRange(http_url, headers, offset, size, +			{				 +				ret = mCurlRequest->getByteRange(http_url, headers, offset, size,  										   new LLMeshDecompositionResponder(mesh_id, offset, size)); +				if(ret) +				{ +					++sActiveLODRequests; +					LLMeshRepository::sHTTPRequestCount++; +				}  			}  		}  	} @@ -791,7 +804,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  	}  	//early out was not hit, effectively fetched -	return true; +	return ret;  }  bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) @@ -805,6 +818,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  	}  	U32 header_size = mMeshHeaderSize[mesh_id]; +	bool ret = true ;  	if (header_size > 0)  	{ @@ -850,11 +864,15 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{ -				++sActiveLODRequests; -				LLMeshRepository::sHTTPRequestCount++; -				mCurlRequest->getByteRange(http_url, headers, offset, size, +			{				 +				ret = mCurlRequest->getByteRange(http_url, headers, offset, size,  										   new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); + +				if(ret) +				{ +					++sActiveLODRequests; +					LLMeshRepository::sHTTPRequestCount++; +				}  			}  		}  		else @@ -868,13 +886,12 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  	}  	//early out was not hit, effectively fetched -	return true; +	return ret;  } -bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params) +//return false if failed to get header +bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count)  { -	bool retval = false; -  	{  		//look for mesh in asset in vfs  		LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH); @@ -889,36 +906,40 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params)  			file.read(buffer, bytes);  			if (headerReceived(mesh_params, buffer, bytes))  			{ //did not do an HTTP request, return false -				return false; +				return true;  			}  		}  	} -	//either cache entry doesn't exist or is corrupt, request header from simulator - +	//either cache entry doesn't exist or is corrupt, request header from simulator	 +	bool retval = true ;  	std::vector<std::string> headers;  	headers.push_back("Accept: application/octet-stream");  	std::string http_url = constructUrl(mesh_params.getSculptID());  	if (!http_url.empty())  	{ -		++sActiveHeaderRequests; -		retval = true;  		//grab first 4KB if we're going to bother with a fetch.  Cache will prevent future fetches if a full mesh fits  		//within the first 4KB -		//NOTE -- this will break of headers ever exceed 4KB -		LLMeshRepository::sHTTPRequestCount++; -		mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params)); +		//NOTE -- this will break of headers ever exceed 4KB		 +		retval = mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params)); +		if(retval) +		{ +			++sActiveHeaderRequests; +			LLMeshRepository::sHTTPRequestCount++; +		} +		count++;  	}  	return retval;  } -bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +//return false if failed to get mesh lod. +bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count)  { //protected by mMutex  	mHeaderMutex->lock(); -	bool retval = false; +	bool retval = true;  	LLUUID mesh_id = mesh_params.getSculptID(); @@ -955,7 +976,7 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  					if (lodReceived(mesh_params, lod, buffer, size))  					{  						delete[] buffer; -						return false; +						return true;  					}  				} @@ -968,12 +989,16 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod)  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{ -				++sActiveLODRequests; -				retval = true; -				LLMeshRepository::sHTTPRequestCount++; -				mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, +			{				 +				retval = mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size,  										   new LLMeshLODResponder(mesh_params, lod, offset, size)); + +				if(retval) +				{ +					++sActiveLODRequests;				 +					LLMeshRepository::sHTTPRequestCount++; +				} +				count++;  			}  			else  			{ @@ -1540,8 +1565,17 @@ void LLMeshUploadThread::doWholeModelUpload()  		LLSD body = full_model_data["asset_resources"];  		dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num));  		LLCurlRequest::headers_t headers; -		mCurlRequest->post(mWholeModelUploadURL, headers, body, -						   new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle), mMeshUploadTimeOut); + +		{ +			LLCurl::ResponderPtr responder = new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle) ; + +			while(!mCurlRequest->post(mWholeModelUploadURL, headers, body, responder, mMeshUploadTimeOut)) +			{ +				//sleep for 10ms to prevent eating a whole core +				apr_sleep(10000); +			} +		} +  		do  		{  			mCurlRequest->process(); @@ -1571,8 +1605,15 @@ void LLMeshUploadThread::requestWholeModelFee()  	mPendingUploads++;  	LLCurlRequest::headers_t headers; -	mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, -					   new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle), mMeshUploadTimeOut); + +	{ +		LLCurl::ResponderPtr responder = new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle) ; +		while(!mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, responder, mMeshUploadTimeOut)) +		{ +			//sleep for 10ms to prevent eating a whole core +			apr_sleep(10000); +		} +	}  	do  	{ diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 27e8aef57c..1b7954d4bd 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -323,8 +323,8 @@ public:  	virtual void run();  	void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); -	bool fetchMeshHeader(const LLVolumeParams& mesh_params); -	bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod); +	bool fetchMeshHeader(const LLVolumeParams& mesh_params, U32& count); +	bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, U32& count);  	bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size);  	bool lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size);  	bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size); diff --git a/indra/newview/llpathfindinglinkset.cpp b/indra/newview/llpathfindinglinkset.cpp new file mode 100644 index 0000000000..daa308f862 --- /dev/null +++ b/indra/newview/llpathfindinglinkset.cpp @@ -0,0 +1,356 @@ +/** 
 + * @file llpathfindinglinksets.cpp
 + * @author William Todd Stinson
 + * @brief Definition of a pathfinding linkset that contains various properties required for havok pathfinding.
 + *
 + * $LicenseInfo:firstyear=2002&license=viewerlgpl$
 + * Second Life Viewer Source Code
 + * Copyright (C) 2010, 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 "llviewerprecompiledheaders.h"
 +#include "llpathfindinglinkset.h"
 +#include "llsd.h"
 +#include "v3math.h"
 +#include "lluuid.h"
 +
 +#define LINKSET_NAME_FIELD          "name"
 +#define LINKSET_DESCRIPTION_FIELD   "description"
 +#define LINKSET_LAND_IMPACT_FIELD   "landimpact"
 +#define LINKSET_PERMANENT_FIELD     "permanent"
 +#define LINKSET_WALKABLE_FIELD      "walkable"
 +#define LINKSET_PHANTOM_FIELD       "phantom"
 +#define LINKSET_WALKABILITY_A_FIELD "A"
 +#define LINKSET_WALKABILITY_B_FIELD "B"
 +#define LINKSET_WALKABILITY_C_FIELD "C"
 +#define LINKSET_WALKABILITY_D_FIELD "D"
 +#define LINKSET_POSITION_FIELD      "position"
 +
 +//---------------------------------------------------------------------------
 +// LLPathfindingLinkset
 +//---------------------------------------------------------------------------
 +
 +const S32 LLPathfindingLinkset::MIN_WALKABILITY_VALUE(0);
 +const S32 LLPathfindingLinkset::MAX_WALKABILITY_VALUE(100);
 +
 +LLPathfindingLinkset::LLPathfindingLinkset(const std::string &pUUID, const LLSD& pLinksetItem)
 +	: mUUID(pUUID),
 +	mName(),
 +	mDescription(),
 +	mLandImpact(0U),
 +	mLocation(),
 +	mPathState(kIgnored),
 +	mIsPhantom(false),
 +#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	mIsWalkabilityCoefficientsF32(false),
 +#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	mWalkabilityCoefficientA(MIN_WALKABILITY_VALUE),
 +	mWalkabilityCoefficientB(MIN_WALKABILITY_VALUE),
 +	mWalkabilityCoefficientC(MIN_WALKABILITY_VALUE),
 +	mWalkabilityCoefficientD(MIN_WALKABILITY_VALUE)
 +{
 +	llassert(pLinksetItem.has(LINKSET_NAME_FIELD));
 +	llassert(pLinksetItem.get(LINKSET_NAME_FIELD).isString());
 +	mName = pLinksetItem.get(LINKSET_NAME_FIELD).asString();
 +
 +	llassert(pLinksetItem.has(LINKSET_DESCRIPTION_FIELD));
 +	llassert(pLinksetItem.get(LINKSET_DESCRIPTION_FIELD).isString());
 +	mDescription = pLinksetItem.get(LINKSET_DESCRIPTION_FIELD).asString();
 +
 +	llassert(pLinksetItem.has(LINKSET_LAND_IMPACT_FIELD));
 +	llassert(pLinksetItem.get(LINKSET_LAND_IMPACT_FIELD).isInteger());
 +	llassert(pLinksetItem.get(LINKSET_LAND_IMPACT_FIELD).asInteger() >= 0);
 +	mLandImpact = pLinksetItem.get(LINKSET_LAND_IMPACT_FIELD).asInteger();
 +
 +	llassert(pLinksetItem.has(LINKSET_PERMANENT_FIELD));
 +	llassert(pLinksetItem.get(LINKSET_PERMANENT_FIELD).isBoolean());
 +	bool isPermanent = pLinksetItem.get(LINKSET_PERMANENT_FIELD).asBoolean();
 +
 +	llassert(pLinksetItem.has(LINKSET_WALKABLE_FIELD));
 +	llassert(pLinksetItem.get(LINKSET_WALKABLE_FIELD).isBoolean());
 +	bool isWalkable = pLinksetItem.get(LINKSET_WALKABLE_FIELD).asBoolean();
 +
 +	mPathState = getPathState(isPermanent, isWalkable);
 +
 +	llassert(pLinksetItem.has(LINKSET_PHANTOM_FIELD));
 +	llassert(pLinksetItem.get(LINKSET_PHANTOM_FIELD).isBoolean());
 +	mIsPhantom = pLinksetItem.get(LINKSET_PHANTOM_FIELD).asBoolean();
 +
 +	llassert(pLinksetItem.has(LINKSET_WALKABILITY_A_FIELD));
 +#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	mIsWalkabilityCoefficientsF32 = pLinksetItem.get(LINKSET_WALKABILITY_A_FIELD).isReal();
 +	if (mIsWalkabilityCoefficientsF32)
 +	{
 +		// Old server-side storage was real
 +		mWalkabilityCoefficientA = llround(pLinksetItem.get(LINKSET_WALKABILITY_A_FIELD).asReal() * 100.0f);
 +
 +		llassert(pLinksetItem.has(LINKSET_WALKABILITY_B_FIELD));
 +		llassert(pLinksetItem.get(LINKSET_WALKABILITY_B_FIELD).isReal());
 +		mWalkabilityCoefficientB = llround(pLinksetItem.get(LINKSET_WALKABILITY_B_FIELD).asReal() * 100.0f);
 +
 +		llassert(pLinksetItem.has(LINKSET_WALKABILITY_C_FIELD));
 +		llassert(pLinksetItem.get(LINKSET_WALKABILITY_C_FIELD).isReal());
 +		mWalkabilityCoefficientC = llround(pLinksetItem.get(LINKSET_WALKABILITY_C_FIELD).asReal() * 100.0f);
 +
 +		llassert(pLinksetItem.has(LINKSET_WALKABILITY_D_FIELD));
 +		llassert(pLinksetItem.get(LINKSET_WALKABILITY_D_FIELD).isReal());
 +		mWalkabilityCoefficientD = llround(pLinksetItem.get(LINKSET_WALKABILITY_D_FIELD).asReal() * 100.0f);
 +	}
 +	else
 +	{
 +		// New server-side storage will be integer
 +		llassert(pLinksetItem.get(LINKSET_WALKABILITY_A_FIELD).isInteger());
 +		mWalkabilityCoefficientA = pLinksetItem.get(LINKSET_WALKABILITY_A_FIELD).asInteger();
 +		llassert(mWalkabilityCoefficientA >= MIN_WALKABILITY_VALUE);
 +		llassert(mWalkabilityCoefficientA <= MAX_WALKABILITY_VALUE);
 +
 +		llassert(pLinksetItem.has(LINKSET_WALKABILITY_B_FIELD));
 +		llassert(pLinksetItem.get(LINKSET_WALKABILITY_B_FIELD).isInteger());
 +		mWalkabilityCoefficientB = pLinksetItem.get(LINKSET_WALKABILITY_B_FIELD).asInteger();
 +		llassert(mWalkabilityCoefficientB >= MIN_WALKABILITY_VALUE);
 +		llassert(mWalkabilityCoefficientB <= MAX_WALKABILITY_VALUE);
 +
 +		llassert(pLinksetItem.has(LINKSET_WALKABILITY_C_FIELD));
 +		llassert(pLinksetItem.get(LINKSET_WALKABILITY_C_FIELD).isInteger());
 +		mWalkabilityCoefficientC = pLinksetItem.get(LINKSET_WALKABILITY_C_FIELD).asInteger();
 +		llassert(mWalkabilityCoefficientC >= MIN_WALKABILITY_VALUE);
 +		llassert(mWalkabilityCoefficientC <= MAX_WALKABILITY_VALUE);
 +
 +		llassert(pLinksetItem.has(LINKSET_WALKABILITY_D_FIELD));
 +		llassert(pLinksetItem.get(LINKSET_WALKABILITY_D_FIELD).isInteger());
 +		mWalkabilityCoefficientD = pLinksetItem.get(LINKSET_WALKABILITY_D_FIELD).asInteger();
 +		llassert(mWalkabilityCoefficientD >= MIN_WALKABILITY_VALUE);
 +		llassert(mWalkabilityCoefficientD <= MAX_WALKABILITY_VALUE);
 +	}
 +#else // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	llassert(pLinksetItem.get(LINKSET_WALKABILITY_A_FIELD).isInteger());
 +	mWalkabilityCoefficientA = pLinksetItem.get(LINKSET_WALKABILITY_A_FIELD).asInteger();
 +	llassert(mWalkabilityCoefficientA >= MIN_WALKABILITY_VALUE);
 +	llassert(mWalkabilityCoefficientA <= MAX_WALKABILITY_VALUE);
 +
 +	llassert(pLinksetItem.has(LINKSET_WALKABILITY_B_FIELD));
 +	llassert(pLinksetItem.get(LINKSET_WALKABILITY_B_FIELD).isInteger());
 +	mWalkabilityCoefficientB = pLinksetItem.get(LINKSET_WALKABILITY_B_FIELD).asInteger();
 +	llassert(mWalkabilityCoefficientB >= MIN_WALKABILITY_VALUE);
 +	llassert(mWalkabilityCoefficientB <= MAX_WALKABILITY_VALUE);
 +
 +	llassert(pLinksetItem.has(LINKSET_WALKABILITY_C_FIELD));
 +	llassert(pLinksetItem.get(LINKSET_WALKABILITY_C_FIELD).isInteger());
 +	mWalkabilityCoefficientC = pLinksetItem.get(LINKSET_WALKABILITY_C_FIELD).asInteger();
 +	llassert(mWalkabilityCoefficientC >= MIN_WALKABILITY_VALUE);
 +	llassert(mWalkabilityCoefficientC <= MAX_WALKABILITY_VALUE);
 +
 +	llassert(pLinksetItem.has(LINKSET_WALKABILITY_D_FIELD));
 +	llassert(pLinksetItem.get(LINKSET_WALKABILITY_D_FIELD).isInteger());
 +	mWalkabilityCoefficientD = pLinksetItem.get(LINKSET_WALKABILITY_D_FIELD).asInteger();
 +	llassert(mWalkabilityCoefficientD >= MIN_WALKABILITY_VALUE);
 +	llassert(mWalkabilityCoefficientD <= MAX_WALKABILITY_VALUE);
 +#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +
 +	llassert(pLinksetItem.has(LINKSET_POSITION_FIELD));
 +	llassert(pLinksetItem.get(LINKSET_POSITION_FIELD).isArray());
 +	mLocation.setValue(pLinksetItem.get(LINKSET_POSITION_FIELD));
 +}
 +
 +LLPathfindingLinkset::LLPathfindingLinkset(const LLPathfindingLinkset& pOther)
 +	: mUUID(pOther.mUUID),
 +	mName(pOther.mName),
 +	mDescription(pOther.mDescription),
 +	mLandImpact(pOther.mLandImpact),
 +	mLocation(pOther.mLocation),
 +	mPathState(pOther.mPathState),
 +	mIsPhantom(pOther.mIsPhantom),
 +#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	mIsWalkabilityCoefficientsF32(pOther.mIsWalkabilityCoefficientsF32),
 +#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	mWalkabilityCoefficientA(pOther.mWalkabilityCoefficientA),
 +	mWalkabilityCoefficientB(pOther.mWalkabilityCoefficientB),
 +	mWalkabilityCoefficientC(pOther.mWalkabilityCoefficientC),
 +	mWalkabilityCoefficientD(pOther.mWalkabilityCoefficientD)
 +{
 +}
 +
 +LLPathfindingLinkset::~LLPathfindingLinkset()
 +{
 +}
 +
 +LLPathfindingLinkset& LLPathfindingLinkset::operator =(const LLPathfindingLinkset& pOther)
 +{
 +	mUUID = pOther.mUUID;
 +	mName = pOther.mName;
 +	mDescription = pOther.mDescription;
 +	mLandImpact = pOther.mLandImpact;
 +	mLocation = pOther.mLocation;
 +	mPathState = pOther.mPathState;
 +	mIsPhantom = pOther.mIsPhantom;
 +#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	mIsWalkabilityCoefficientsF32 = pOther.mIsWalkabilityCoefficientsF32;
 +#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	mWalkabilityCoefficientA = pOther.mWalkabilityCoefficientA;
 +	mWalkabilityCoefficientB = pOther.mWalkabilityCoefficientB;
 +	mWalkabilityCoefficientC = pOther.mWalkabilityCoefficientC;
 +	mWalkabilityCoefficientD = pOther.mWalkabilityCoefficientD;
 +
 +	return *this;
 +}
 +
 +
 +LLPathfindingLinkset::EPathState LLPathfindingLinkset::getPathState(bool pIsPermanent, bool pIsWalkable)
 +{
 +	return (pIsPermanent ? (pIsWalkable ? kWalkable : kObstacle) : kIgnored);
 +}
 +
 +BOOL LLPathfindingLinkset::isPermanent(EPathState pPathState)
 +{
 +	BOOL retVal;
 +
 +	switch (pPathState)
 +	{
 +	case kWalkable :
 +	case kObstacle :
 +		retVal = true;
 +		break;
 +	case kIgnored :
 +		retVal = false;
 +		break;
 +	default :
 +		retVal = false;
 +		llassert(0);
 +		break;
 +	}
 +
 +	return retVal;
 +}
 +
 +BOOL LLPathfindingLinkset::isWalkable(EPathState pPathState)
 +{
 +	BOOL retVal;
 +
 +	switch (pPathState)
 +	{
 +	case kWalkable :
 +		retVal = true;
 +		break;
 +	case kObstacle :
 +	case kIgnored :
 +		retVal = false;
 +		break;
 +	default :
 +		retVal = false;
 +		llassert(0);
 +		break;
 +	}
 +
 +	return retVal;
 +}
 +
 +void LLPathfindingLinkset::setWalkabilityCoefficientA(S32 pA)
 +{
 +	mWalkabilityCoefficientA = llclamp(pA, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +}
 +
 +void LLPathfindingLinkset::setWalkabilityCoefficientB(S32 pB)
 +{
 +	mWalkabilityCoefficientB = llclamp(pB, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +}
 +
 +void LLPathfindingLinkset::setWalkabilityCoefficientC(S32 pC)
 +{
 +	mWalkabilityCoefficientC = llclamp(pC, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +}
 +
 +void LLPathfindingLinkset::setWalkabilityCoefficientD(S32 pD)
 +{
 +	mWalkabilityCoefficientD = llclamp(pD, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +}
 +
 +LLSD LLPathfindingLinkset::encodeAlteredFields(EPathState pPathState, S32 pA, S32 pB, S32 pC, S32 pD, BOOL pIsPhantom) const
 +{
 +	LLSD itemData;
 +
 +	if (mPathState != pPathState)
 +	{
 +		itemData[LINKSET_PERMANENT_FIELD] = static_cast<bool>(LLPathfindingLinkset::isPermanent(pPathState));
 +		itemData[LINKSET_WALKABLE_FIELD] = static_cast<bool>(LLPathfindingLinkset::isWalkable(pPathState));
 +	}
 +#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	if (mIsWalkabilityCoefficientsF32)
 +	{
 +		if (mWalkabilityCoefficientA != pA)
 +		{
 +			itemData[LINKSET_WALKABILITY_A_FIELD] = llclamp(static_cast<F32>(pA) / 100.0f, 0.0f, 1.0f);
 +		}
 +		if (mWalkabilityCoefficientB != pB)
 +		{
 +			itemData[LINKSET_WALKABILITY_B_FIELD] = llclamp(static_cast<F32>(pB) / 100.0f, 0.0f, 1.0f);
 +		}
 +		if (mWalkabilityCoefficientC != pC)
 +		{
 +			itemData[LINKSET_WALKABILITY_C_FIELD] = llclamp(static_cast<F32>(pC) / 100.0f, 0.0f, 1.0f);
 +		}
 +		if (mWalkabilityCoefficientD != pD)
 +		{
 +			itemData[LINKSET_WALKABILITY_D_FIELD] = llclamp(static_cast<F32>(pD) / 100.0f, 0.0f, 1.0f);
 +		}
 +	}
 +	else
 +	{
 +		if (mWalkabilityCoefficientA != pA)
 +		{
 +			itemData[LINKSET_WALKABILITY_A_FIELD] = llclamp(pA, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +		}
 +		if (mWalkabilityCoefficientB != pB)
 +		{
 +			itemData[LINKSET_WALKABILITY_B_FIELD] = llclamp(pB, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +		}
 +		if (mWalkabilityCoefficientC != pC)
 +		{
 +			itemData[LINKSET_WALKABILITY_C_FIELD] = llclamp(pC, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +		}
 +		if (mWalkabilityCoefficientD != pD)
 +		{
 +			itemData[LINKSET_WALKABILITY_D_FIELD] = llclamp(pD, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +		}
 +	}
 +#else // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	if (mWalkabilityCoefficientA != pA)
 +	{
 +		itemData[LINKSET_WALKABILITY_A_FIELD] = llclamp(pA, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +	}
 +	if (mWalkabilityCoefficientB != pB)
 +	{
 +		itemData[LINKSET_WALKABILITY_B_FIELD] = llclamp(pB, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +	}
 +	if (mWalkabilityCoefficientC != pC)
 +	{
 +		itemData[LINKSET_WALKABILITY_C_FIELD] = llclamp(pC, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +	}
 +	if (mWalkabilityCoefficientD != pD)
 +	{
 +		itemData[LINKSET_WALKABILITY_D_FIELD] = llclamp(pD, MIN_WALKABILITY_VALUE, MAX_WALKABILITY_VALUE);
 +	}
 +#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	if (mIsPhantom != pIsPhantom)
 +	{
 +		itemData[LINKSET_PHANTOM_FIELD] = static_cast<bool>(pIsPhantom);
 +	}
 +
 +	return itemData;
 +}
 diff --git a/indra/newview/llpathfindinglinkset.h b/indra/newview/llpathfindinglinkset.h new file mode 100644 index 0000000000..d4e58874eb --- /dev/null +++ b/indra/newview/llpathfindinglinkset.h @@ -0,0 +1,108 @@ +/** 
 + * @file llpathfindinglinkset.h
 + * @author William Todd Stinson
 + * @brief Definition of a pathfinding linkset that contains various properties required for havok pathfinding.
 + *
 + * $LicenseInfo:firstyear=2002&license=viewerlgpl$
 + * Second Life Viewer Source Code
 + * Copyright (C) 2010, 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_LLPATHFINDINGLINKSET_H
 +#define LL_LLPATHFINDINGLINKSET_H
 +
 +#include "v3math.h"
 +#include "lluuid.h"
 +
 +// This is a reminder to remove the code regarding the changing of the data type for the
 +// walkability coefficients from F32 to S32 representing the percentage from 0-100.
 +#define XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +
 +class LLSD;
 +
 +class LLPathfindingLinkset
 +{
 +public:
 +	typedef enum
 +	{
 +		kWalkable,
 +		kObstacle,
 +		kIgnored
 +	} EPathState;
 +
 +	LLPathfindingLinkset(const std::string &pUUID, const LLSD &pLinksetItem);
 +	LLPathfindingLinkset(const LLPathfindingLinkset& pOther);
 +	virtual ~LLPathfindingLinkset();
 +
 +	LLPathfindingLinkset& operator = (const LLPathfindingLinkset& pOther);
 +
 +	inline const LLUUID&      getUUID() const                     {return mUUID;};
 +	inline const std::string& getName() const                     {return mName;};
 +	inline const std::string& getDescription() const              {return mDescription;};
 +	inline U32                getLandImpact() const               {return mLandImpact;};
 +	inline const LLVector3&   getLocation() const                 {return mLocation;};
 +
 +	inline EPathState         getPathState() const                {return mPathState;};
 +	inline void               setPathState(EPathState pPathState) {mPathState = pPathState;};
 +
 +	static EPathState         getPathState(bool pIsPermanent, bool pIsWalkable);
 +	static BOOL               isPermanent(EPathState pPathState);
 +	static BOOL               isWalkable(EPathState pPathState);
 +
 +	inline BOOL               isPhantom() const                   {return mIsPhantom;};
 +	inline void               setPhantom(BOOL pIsPhantom)         {mIsPhantom = pIsPhantom;};
 +
 +	inline S32                getWalkabilityCoefficientA() const  {return mWalkabilityCoefficientA;};
 +	void                      setWalkabilityCoefficientA(S32 pA);
 +
 +	inline S32                getWalkabilityCoefficientB() const  {return mWalkabilityCoefficientB;};
 +	void                      setWalkabilityCoefficientB(S32 pB);
 +
 +	inline S32                getWalkabilityCoefficientC() const  {return mWalkabilityCoefficientC;};
 +	void                      setWalkabilityCoefficientC(S32 pC);
 +
 +	inline S32                getWalkabilityCoefficientD() const  {return mWalkabilityCoefficientD;};
 +	void                      setWalkabilityCoefficientD(S32 pD);
 +
 +	LLSD                      encodeAlteredFields(EPathState pPathState, S32 pA, S32 pB, S32 pC, S32 pD, BOOL pIsPhantom) const;
 +
 +protected:
 +
 +private:
 +	static const S32 MIN_WALKABILITY_VALUE;
 +	static const S32 MAX_WALKABILITY_VALUE;
 +
 +	LLUUID      mUUID;
 +	std::string mName;
 +	std::string mDescription;
 +	U32         mLandImpact;
 +	LLVector3   mLocation;
 +	EPathState  mPathState;
 +	BOOL        mIsPhantom;
 +#ifdef XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	BOOL        mIsWalkabilityCoefficientsF32;
 +#endif // XXX_STINSON_WALKABILITY_COEFFICIENTS_TYPE_CHANGE
 +	S32         mWalkabilityCoefficientA;
 +	S32         mWalkabilityCoefficientB;
 +	S32         mWalkabilityCoefficientC;
 +	S32         mWalkabilityCoefficientD;
 +};
 +
 +#endif // LL_LLPATHFINDINGLINKSET_H
 diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index e8029293fc..3e21334cd4 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -885,7 +885,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  		LLAppViewer::instance()->pingMainloopTimeout("Display:RenderGeom");  		bool exclusiveDraw = false;  		BOOL allowRenderables = false; -		BOOL allowPathToBeDrawn = false;  		if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())  				&& !gRestoreGL)  		{ @@ -899,38 +898,31 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  			else  			{  				//Render any navmesh geometry	 -				if ( LLPathingLib::getInstance() )  +				LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance(); +				if ( llPathingLibInstance != NULL )   				{	  					//Determine if we can should overlay the navmesh ontop of the scenes typical renderables -					LLFloaterPathfindingConsole* pFloater = LLFloaterReg::getTypedInstance<LLFloaterPathfindingConsole>("pathfinding_console"); -					if ( pFloater && pFloater->allowAllRenderables() ) -					{ -						allowRenderables = true; -					} -					//Determine if we should also draw a user supplied path on top of the scene -					if ( pFloater && pFloater->getShowPathToggle() ) -					{ -						allowPathToBeDrawn = true; -					} +					allowRenderables = llPathingLibInstance->getRenderOverlayMode(); +  					//NavMesh -					if ( LLPathingLib::getInstance()->getRenderNavMeshState() ) +					if ( llPathingLibInstance->getRenderNavMeshState() )  					{  						glClearColor(0.0f, 0.0f, 0.0f, 0.5f);          												  						glEnable(GL_DEPTH_TEST);                          						gGL.setAmbientLightColor( LLColor4::white ); -						LLPathingLib::getInstance()->renderNavMesh( allowRenderables ); +						llPathingLibInstance->renderNavMesh();  						exclusiveDraw = true;  					}  					//physics/exclusion shapes -					if ( LLPathingLib::getInstance()->getRenderShapeState() ) +					if ( llPathingLibInstance->getRenderShapesState() )  					{						 -						LLPathingLib::getInstance()->renderNavMeshShapesVBO(); +						llPathingLibInstance->renderNavMeshShapesVBO();  						exclusiveDraw = true;  					}	  					//User designated path -					if ( allowPathToBeDrawn ) +					if ( llPathingLibInstance->getRenderPathState() )  					{ -						LLPathingLib::getInstance()->renderPath(); +						llPathingLibInstance->renderPath();  					}  				}			  			} diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 7f2aefcc2b..ab03463bbc 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1984,33 +1984,42 @@ void LLViewerWindow::shutdownViews()  	// clean up warning logger  	LLError::removeRecorder(RecordToChatConsole::getInstance()); +	llinfos << "Warning logger is cleaned." << llendl ; +  	delete mDebugText;  	mDebugText = NULL; +	llinfos << "DebugText deleted." << llendl ; +  	// Cleanup global views  	if (gMorphView)  	{  		gMorphView->setVisible(FALSE);  	} +	llinfos << "Global views cleaned." << llendl ;  	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open  	// will crump with LL_ERRS.  	LLModalDialog::shutdownModals(); -	 +	llinfos << "LLModalDialog shut down." << llendl;  +  	// destroy the nav bar, not currently part of gViewerWindow  	// *TODO: Make LLNavigationBar part of gViewerWindow  	if (LLNavigationBar::instanceExists())  	{  		delete LLNavigationBar::getInstance();  	} +	llinfos << "LLNavigationBar destroyed." << llendl ;  	// destroy menus after instantiating navbar above, as it needs  	// access to gMenuHolder  	cleanup_menus(); +	llinfos << "menus destroyed." << llendl ;  	// Delete all child views.  	delete mRootView;  	mRootView = NULL; +	llinfos << "RootView deleted." << llendl ;  	// Automatically deleted as children of mRootView.  Fix the globals.  	gStatusBar = NULL; diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 920a9a3752..0da70d398b 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -305,6 +305,15 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip)  	{  		mCurlRequest = new LLCurlEasyRequest();  	} +	if(!mCurlRequest->isValid()) +	{ +		llwarns << "mCurlRequest is invalid." << llendl ; + +		delete mCurlRequest ; +		mCurlRequest = NULL ; +		return ; +	} +  	mErrorCert = NULL;  //	mCurlRequest->setopt(CURLOPT_VERBOSE, 1); // useful for debugging @@ -357,10 +366,20 @@ LLXMLRPCTransaction::Impl::~Impl()  	}  	delete mCurlRequest; +	mCurlRequest = NULL ;  }  bool LLXMLRPCTransaction::Impl::process()  { +	if(!mCurlRequest || !mCurlRequest->isValid()) +	{ +		llwarns << "transaction failed." << llendl ; + +		delete mCurlRequest ; +		mCurlRequest = NULL ; +		return true ; //failed, quit. +	} +  	switch(mStatus)  	{  		case LLXMLRPCTransaction::StatusComplete: diff --git a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml index e5d06481e5..65c0bf3cca 100644 --- a/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml +++ b/indra/newview/skins/default/xui/en/floater_pathfinding_linksets.xml @@ -94,7 +94,7 @@        width="106" />    <check_box        height="19" -      initial_value="1" +      initial_value="true"        label="Walkable"        layout="topleft"        left="481" @@ -103,7 +103,7 @@        width="90" />    <check_box        height="19" -      initial_value="1" +      initial_value="true"        label="Obstacle"        layout="topleft"        left="577" @@ -112,7 +112,7 @@        width="90" />    <check_box        height="19" -      initial_value="1" +      initial_value="true"        label="Ignored"        layout="topleft"        left="674" diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index e88d1bf811..19ac418e9e 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -39,7 +39,7 @@  #include "llsdserialize.h"  #include "llthread.h"  #include "llupdaterservice.h" - +#include "llcurl.h"  class LLUpdateDownloader::Implementation:  	public LLThread @@ -198,13 +198,19 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client &  LLUpdateDownloader::Implementation::~Implementation()  { -	if(isDownloading()) { +	if(isDownloading())  +	{  		cancel();  		shutdown(); -	} else { +	}  +	else  +	{  		; // No op.  	} -	if(mCurl) curl_easy_cleanup(mCurl); +	if(mCurl) +	{ +		LLCurl::deleteEasyHandle(mCurl); +	}  } @@ -406,9 +412,12 @@ void LLUpdateDownloader::Implementation::run(void)  void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & url, bool processHeader)  { -	if(mCurl == 0) { -		mCurl = curl_easy_init(); -	} else { +	if(mCurl == 0)  +	{ +		mCurl = LLCurl::newEasyHandle(); +	}  +	else  +	{  		curl_easy_reset(mCurl);  	}  | 
