merge changes for vmrg-219
commit
1ed8faee81
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
//
|
||||
|
|
|
|||
|
|
@ -75,6 +75,12 @@ LLIOPipe::~LLIOPipe()
|
|||
//lldebugs << "destroying LLIOPipe" << llendl;
|
||||
}
|
||||
|
||||
//virtual
|
||||
bool LLIOPipe::isValid()
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
// static
|
||||
std::string LLIOPipe::lookupStatusString(EStatus status)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -231,6 +231,8 @@ public:
|
|||
*/
|
||||
virtual ~LLIOPipe();
|
||||
|
||||
virtual bool isValid() ;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Base Constructor.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -188,6 +188,8 @@ public:
|
|||
*/
|
||||
void allowCookies();
|
||||
|
||||
/*virtual*/ bool isValid() ;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Give this pipe a chance to handle a generated error
|
||||
|
|
|
|||
|
|
@ -1434,6 +1434,8 @@ void LLRender::loadIdentity()
|
|||
flush();
|
||||
|
||||
{
|
||||
llassert_always(mMatrixMode < NUM_MATRIX_MODES) ;
|
||||
|
||||
mMatrix[mMatrixMode][mMatIdx[mMatrixMode]].make_identity();
|
||||
mMatHash[mMatrixMode]++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -722,7 +722,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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -1958,33 +1958,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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue