Merge viewer-64
commit
13b6febd34
|
|
@ -3431,9 +3431,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>01b463520b0f253842335428901404ae</string>
|
||||
<string>333a679f0a492e060b4586eaa1a38a56</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/7371/27810/viewer_manager-1.0.507360-darwin64-507360.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/7692/29540/viewer_manager-1.0.507681-darwin64-507681.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -3455,9 +3455,9 @@
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>2f8626ce0448d56ecfd07e51affadcfd</string>
|
||||
<string>bf4672af39013418d721327d337ba1a0</string>
|
||||
<key>url</key>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/7372/27832/viewer_manager-1.0.507360-windows-507360.tar.bz2</string>
|
||||
<string>http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/7694/29546/viewer_manager-1.0.507681-windows-507681.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
|
@ -3468,7 +3468,7 @@
|
|||
<key>source_type</key>
|
||||
<string>hg</string>
|
||||
<key>version</key>
|
||||
<string>1.0.507360</string>
|
||||
<string>1.0.507681</string>
|
||||
</map>
|
||||
<key>vlc-bin</key>
|
||||
<map>
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@ set(llcommon_HEADER_FILES
|
|||
llstring.h
|
||||
llstringtable.h
|
||||
llstaticstringtable.h
|
||||
llstatsaccumulator.h
|
||||
llsys.h
|
||||
llthread.h
|
||||
llthreadlocalstorage.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,120 @@
|
|||
/**
|
||||
* @file llstatsaccumulator.h
|
||||
* @brief Class for accumulating statistics.
|
||||
*
|
||||
* $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_STATS_ACCUMULATOR_H
|
||||
#define LL_STATS_ACCUMULATOR_H
|
||||
#include "llsd.h"
|
||||
|
||||
class LLStatsAccumulator
|
||||
{
|
||||
public:
|
||||
inline LLStatsAccumulator()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
inline void push(F32 val)
|
||||
{
|
||||
if (mCountOfNextUpdatesToIgnore > 0)
|
||||
{
|
||||
mCountOfNextUpdatesToIgnore--;
|
||||
return;
|
||||
}
|
||||
|
||||
mCount++;
|
||||
mSum += val;
|
||||
mSumOfSquares += val * val;
|
||||
if (mCount == 1 || val > mMaxValue)
|
||||
{
|
||||
mMaxValue = val;
|
||||
}
|
||||
if (mCount == 1 || val < mMinValue)
|
||||
{
|
||||
mMinValue = val;
|
||||
}
|
||||
}
|
||||
|
||||
inline F32 getSum() const
|
||||
{
|
||||
return mSum;
|
||||
}
|
||||
|
||||
inline F32 getMean() const
|
||||
{
|
||||
return (mCount == 0) ? 0.f : ((F32)mSum) / mCount;
|
||||
}
|
||||
|
||||
inline F32 getMinValue() const
|
||||
{
|
||||
return mMinValue;
|
||||
}
|
||||
|
||||
inline F32 getMaxValue() const
|
||||
{
|
||||
return mMaxValue;
|
||||
}
|
||||
|
||||
inline F32 getStdDev() const
|
||||
{
|
||||
const F32 mean = getMean();
|
||||
return (mCount < 2) ? 0.f : sqrtf(llmax(0.f, mSumOfSquares / mCount - (mean * mean)));
|
||||
}
|
||||
|
||||
inline U32 getCount() const
|
||||
{
|
||||
return mCount;
|
||||
}
|
||||
|
||||
inline void reset()
|
||||
{
|
||||
mCount = 0;
|
||||
mSum = mSumOfSquares = 0.f;
|
||||
mMinValue = 0.0f;
|
||||
mMaxValue = 0.0f;
|
||||
mCountOfNextUpdatesToIgnore = 0;
|
||||
}
|
||||
|
||||
inline LLSD asLLSD() const
|
||||
{
|
||||
LLSD data;
|
||||
data["mean"] = getMean();
|
||||
data["std_dev"] = getStdDev();
|
||||
data["count"] = (S32)mCount;
|
||||
data["min"] = getMinValue();
|
||||
data["max"] = getMaxValue();
|
||||
return data;
|
||||
}
|
||||
|
||||
private:
|
||||
S32 mCount;
|
||||
F32 mSum;
|
||||
F32 mSumOfSquares;
|
||||
F32 mMinValue;
|
||||
F32 mMaxValue;
|
||||
U32 mCountOfNextUpdatesToIgnore;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -34,6 +34,7 @@
|
|||
#include "lltimer.h"
|
||||
#include "lltrace.h"
|
||||
#include "lltracethreadrecorder.h"
|
||||
#include "llexception.h"
|
||||
|
||||
#if LL_LINUX || LL_SOLARIS
|
||||
#include <sched.h>
|
||||
|
|
@ -46,28 +47,28 @@ const DWORD MS_VC_EXCEPTION=0x406D1388;
|
|||
#pragma pack(push,8)
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
DWORD dwType; // Must be 0x1000.
|
||||
LPCSTR szName; // Pointer to name (in user addr space).
|
||||
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
||||
DWORD dwFlags; // Reserved for future use, must be zero.
|
||||
} THREADNAME_INFO;
|
||||
#pragma pack(pop)
|
||||
|
||||
void set_thread_name( DWORD dwThreadID, const char* threadName)
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = threadName;
|
||||
info.dwThreadID = dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
info.szName = threadName;
|
||||
info.dwThreadID = dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info );
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
__try
|
||||
{
|
||||
::RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info );
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
{
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -99,17 +100,17 @@ U32 LLThread::sIDIter = 0;
|
|||
|
||||
LL_COMMON_API void assert_main_thread()
|
||||
{
|
||||
static U32 s_thread_id = LLThread::currentID();
|
||||
if (LLThread::currentID() != s_thread_id)
|
||||
{
|
||||
LL_WARNS() << "Illegal execution from thread id " << (S32) LLThread::currentID()
|
||||
<< " outside main thread " << (S32) s_thread_id << LL_ENDL;
|
||||
}
|
||||
static U32 s_thread_id = LLThread::currentID();
|
||||
if (LLThread::currentID() != s_thread_id)
|
||||
{
|
||||
LL_WARNS() << "Illegal execution from thread id " << (S32) LLThread::currentID()
|
||||
<< " outside main thread " << (S32) s_thread_id << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
void LLThread::registerThreadID()
|
||||
{
|
||||
sThreadID = ++sIDIter;
|
||||
sThreadID = ++sIDIter;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -117,157 +118,203 @@ void LLThread::registerThreadID()
|
|||
//
|
||||
void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap)
|
||||
{
|
||||
LLThread *threadp = (LLThread *)datap;
|
||||
LLThread *threadp = (LLThread *)datap;
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
set_thread_name(-1, threadp->mName.c_str());
|
||||
set_thread_name(-1, threadp->mName.c_str());
|
||||
#endif
|
||||
|
||||
// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
|
||||
threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
|
||||
// for now, hard code all LLThreads to report to single master thread recorder, which is known to be running on main thread
|
||||
threadp->mRecorder = new LLTrace::ThreadRecorder(*LLTrace::get_master_thread_recorder());
|
||||
|
||||
sThreadID = threadp->mID;
|
||||
sThreadID = threadp->mID;
|
||||
|
||||
// Run the user supplied function
|
||||
threadp->run();
|
||||
try
|
||||
{
|
||||
// Run the user supplied function
|
||||
do
|
||||
{
|
||||
try
|
||||
{
|
||||
threadp->run();
|
||||
}
|
||||
catch (const LLContinueError &e)
|
||||
{
|
||||
LL_WARNS("THREAD") << "ContinueException on thread '" << threadp->mName <<
|
||||
"' reentering run(). Error what is: '" << e.what() << "'" << LL_ENDL;
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print();
|
||||
|
||||
//LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL;
|
||||
|
||||
delete threadp->mRecorder;
|
||||
threadp->mRecorder = NULL;
|
||||
|
||||
// We're done with the run function, this thread is done executing now.
|
||||
//NB: we are using this flag to sync across threads...we really need memory barriers here
|
||||
threadp->mStatus = STOPPED;
|
||||
LOG_UNHANDLED_EXCEPTION("LLThread");
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
return NULL;
|
||||
} while (true);
|
||||
|
||||
//LL_INFOS() << "LLThread::staticRun() Exiting: " << threadp->mName << LL_ENDL;
|
||||
|
||||
// We're done with the run function, this thread is done executing now.
|
||||
//NB: we are using this flag to sync across threads...we really need memory barriers here
|
||||
threadp->mStatus = STOPPED;
|
||||
}
|
||||
catch (std::bad_alloc)
|
||||
{
|
||||
threadp->mStatus = CRASHED;
|
||||
LLMemory::logMemoryInfo(TRUE);
|
||||
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print();
|
||||
|
||||
LL_ERRS("THREAD") << "Bad memory allocation in LLThread::staticRun() named '" << threadp->mName << "'!" << LL_ENDL;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
threadp->mStatus = CRASHED;
|
||||
CRASH_ON_UNHANDLED_EXCEPTION("LLThread");
|
||||
}
|
||||
|
||||
delete threadp->mRecorder;
|
||||
threadp->mRecorder = NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
|
||||
mPaused(FALSE),
|
||||
mName(name),
|
||||
mAPRThreadp(NULL),
|
||||
mStatus(STOPPED),
|
||||
mRecorder(NULL)
|
||||
mPaused(FALSE),
|
||||
mName(name),
|
||||
mAPRThreadp(NULL),
|
||||
mStatus(STOPPED),
|
||||
mRecorder(NULL)
|
||||
{
|
||||
|
||||
mID = ++sIDIter;
|
||||
mID = ++sIDIter;
|
||||
|
||||
// Thread creation probably CAN be paranoid about APR being initialized, if necessary
|
||||
if (poolp)
|
||||
{
|
||||
mIsLocalPool = FALSE;
|
||||
mAPRPoolp = poolp;
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsLocalPool = TRUE;
|
||||
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
|
||||
}
|
||||
mRunCondition = new LLCondition(mAPRPoolp);
|
||||
mDataLock = new LLMutex(mAPRPoolp);
|
||||
mLocalAPRFilePoolp = NULL ;
|
||||
// Thread creation probably CAN be paranoid about APR being initialized, if necessary
|
||||
if (poolp)
|
||||
{
|
||||
mIsLocalPool = FALSE;
|
||||
mAPRPoolp = poolp;
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsLocalPool = TRUE;
|
||||
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
|
||||
}
|
||||
mRunCondition = new LLCondition(mAPRPoolp);
|
||||
mDataLock = new LLMutex(mAPRPoolp);
|
||||
mLocalAPRFilePoolp = NULL ;
|
||||
}
|
||||
|
||||
|
||||
LLThread::~LLThread()
|
||||
{
|
||||
shutdown();
|
||||
shutdown();
|
||||
|
||||
if(mLocalAPRFilePoolp)
|
||||
{
|
||||
delete mLocalAPRFilePoolp ;
|
||||
mLocalAPRFilePoolp = NULL ;
|
||||
}
|
||||
if (isCrashed())
|
||||
{
|
||||
LL_WARNS("THREAD") << "Destroying crashed thread named '" << mName << "'" << LL_ENDL;
|
||||
}
|
||||
|
||||
if(mLocalAPRFilePoolp)
|
||||
{
|
||||
delete mLocalAPRFilePoolp ;
|
||||
mLocalAPRFilePoolp = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
void LLThread::shutdown()
|
||||
{
|
||||
// Warning! If you somehow call the thread destructor from itself,
|
||||
// the thread will die in an unclean fashion!
|
||||
if (mAPRThreadp)
|
||||
{
|
||||
if (!isStopped())
|
||||
{
|
||||
// The thread isn't already stopped
|
||||
// First, set the flag that indicates that we're ready to die
|
||||
setQuitting();
|
||||
if (isCrashed())
|
||||
{
|
||||
LL_WARNS("THREAD") << "Shutting down crashed thread named '" << mName << "'" << LL_ENDL;
|
||||
}
|
||||
|
||||
//LL_INFOS() << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << LL_ENDL;
|
||||
// Now wait a bit for the thread to exit
|
||||
// It's unclear whether I should even bother doing this - this destructor
|
||||
// should never get called unless we're already stopped, really...
|
||||
S32 counter = 0;
|
||||
const S32 MAX_WAIT = 600;
|
||||
while (counter < MAX_WAIT)
|
||||
{
|
||||
if (isStopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Sleep for a tenth of a second
|
||||
ms_sleep(100);
|
||||
yield();
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
// Warning! If you somehow call the thread destructor from itself,
|
||||
// the thread will die in an unclean fashion!
|
||||
if (mAPRThreadp)
|
||||
{
|
||||
if (!isStopped())
|
||||
{
|
||||
// The thread isn't already stopped
|
||||
// First, set the flag that indicates that we're ready to die
|
||||
setQuitting();
|
||||
|
||||
if (!isStopped())
|
||||
{
|
||||
// This thread just wouldn't stop, even though we gave it time
|
||||
//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
|
||||
// Put a stake in its heart.
|
||||
delete mRecorder;
|
||||
//LL_INFOS() << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << LL_ENDL;
|
||||
// Now wait a bit for the thread to exit
|
||||
// It's unclear whether I should even bother doing this - this destructor
|
||||
// should never get called unless we're already stopped, really...
|
||||
S32 counter = 0;
|
||||
const S32 MAX_WAIT = 600;
|
||||
while (counter < MAX_WAIT)
|
||||
{
|
||||
if (isStopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Sleep for a tenth of a second
|
||||
ms_sleep(100);
|
||||
yield();
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
apr_thread_exit(mAPRThreadp, -1);
|
||||
return;
|
||||
}
|
||||
mAPRThreadp = NULL;
|
||||
}
|
||||
if (!isStopped())
|
||||
{
|
||||
// This thread just wouldn't stop, even though we gave it time
|
||||
//LL_WARNS() << "LLThread::~LLThread() exiting thread before clean exit!" << LL_ENDL;
|
||||
// Put a stake in its heart.
|
||||
delete mRecorder;
|
||||
|
||||
delete mRunCondition;
|
||||
mRunCondition = NULL;
|
||||
apr_thread_exit(mAPRThreadp, -1);
|
||||
return;
|
||||
}
|
||||
mAPRThreadp = NULL;
|
||||
}
|
||||
|
||||
delete mDataLock;
|
||||
mDataLock = NULL;
|
||||
|
||||
if (mIsLocalPool && mAPRPoolp)
|
||||
{
|
||||
apr_pool_destroy(mAPRPoolp);
|
||||
mAPRPoolp = 0;
|
||||
}
|
||||
delete mRunCondition;
|
||||
mRunCondition = NULL;
|
||||
|
||||
if (mRecorder)
|
||||
{
|
||||
// missed chance to properly shut down recorder (needs to be done in thread context)
|
||||
// probably due to abnormal thread termination
|
||||
// so just leak it and remove it from parent
|
||||
LLTrace::get_master_thread_recorder()->removeChildRecorder(mRecorder);
|
||||
}
|
||||
delete mDataLock;
|
||||
mDataLock = NULL;
|
||||
|
||||
if (mIsLocalPool && mAPRPoolp)
|
||||
{
|
||||
apr_pool_destroy(mAPRPoolp);
|
||||
mAPRPoolp = 0;
|
||||
}
|
||||
|
||||
if (mRecorder)
|
||||
{
|
||||
// missed chance to properly shut down recorder (needs to be done in thread context)
|
||||
// probably due to abnormal thread termination
|
||||
// so just leak it and remove it from parent
|
||||
LLTrace::get_master_thread_recorder()->removeChildRecorder(mRecorder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLThread::start()
|
||||
{
|
||||
llassert(isStopped());
|
||||
|
||||
// Set thread state to running
|
||||
mStatus = RUNNING;
|
||||
llassert(isStopped());
|
||||
|
||||
// Set thread state to running
|
||||
mStatus = RUNNING;
|
||||
|
||||
apr_status_t status =
|
||||
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
|
||||
|
||||
if(status == APR_SUCCESS)
|
||||
{
|
||||
// We won't bother joining
|
||||
apr_thread_detach(mAPRThreadp);
|
||||
}
|
||||
else
|
||||
{
|
||||
mStatus = STOPPED;
|
||||
LL_WARNS() << "failed to start thread " << mName << LL_ENDL;
|
||||
ll_apr_warn_status(status);
|
||||
}
|
||||
apr_status_t status =
|
||||
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
|
||||
|
||||
if(status == APR_SUCCESS)
|
||||
{
|
||||
// We won't bother joining
|
||||
apr_thread_detach(mAPRThreadp);
|
||||
}
|
||||
else
|
||||
{
|
||||
mStatus = STOPPED;
|
||||
LL_WARNS() << "failed to start thread " << mName << LL_ENDL;
|
||||
ll_apr_warn_status(status);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -278,28 +325,28 @@ void LLThread::start()
|
|||
// The thread will pause when (and if) it calls checkPause()
|
||||
void LLThread::pause()
|
||||
{
|
||||
if (!mPaused)
|
||||
{
|
||||
// this will cause the thread to stop execution as soon as checkPause() is called
|
||||
mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread
|
||||
}
|
||||
if (!mPaused)
|
||||
{
|
||||
// this will cause the thread to stop execution as soon as checkPause() is called
|
||||
mPaused = 1; // Does not need to be atomic since this is only set/unset from the main thread
|
||||
}
|
||||
}
|
||||
|
||||
void LLThread::unpause()
|
||||
{
|
||||
if (mPaused)
|
||||
{
|
||||
mPaused = 0;
|
||||
}
|
||||
if (mPaused)
|
||||
{
|
||||
mPaused = 0;
|
||||
}
|
||||
|
||||
wake(); // wake up the thread if necessary
|
||||
wake(); // wake up the thread if necessary
|
||||
}
|
||||
|
||||
// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
|
||||
bool LLThread::runCondition(void)
|
||||
{
|
||||
// by default, always run. Handling of pause/unpause is done regardless of this function's result.
|
||||
return true;
|
||||
// by default, always run. Handling of pause/unpause is done regardless of this function's result.
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
@ -307,65 +354,65 @@ bool LLThread::runCondition(void)
|
|||
// Stop thread execution if requested until unpaused.
|
||||
void LLThread::checkPause()
|
||||
{
|
||||
mDataLock->lock();
|
||||
mDataLock->lock();
|
||||
|
||||
// This is in a while loop because the pthread API allows for spurious wakeups.
|
||||
while(shouldSleep())
|
||||
{
|
||||
mDataLock->unlock();
|
||||
mRunCondition->wait(); // unlocks mRunCondition
|
||||
mDataLock->lock();
|
||||
// mRunCondition is locked when the thread wakes up
|
||||
}
|
||||
|
||||
mDataLock->unlock();
|
||||
// This is in a while loop because the pthread API allows for spurious wakeups.
|
||||
while(shouldSleep())
|
||||
{
|
||||
mDataLock->unlock();
|
||||
mRunCondition->wait(); // unlocks mRunCondition
|
||||
mDataLock->lock();
|
||||
// mRunCondition is locked when the thread wakes up
|
||||
}
|
||||
|
||||
mDataLock->unlock();
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
void LLThread::setQuitting()
|
||||
{
|
||||
mDataLock->lock();
|
||||
if (mStatus == RUNNING)
|
||||
{
|
||||
mStatus = QUITTING;
|
||||
}
|
||||
mDataLock->unlock();
|
||||
wake();
|
||||
mDataLock->lock();
|
||||
if (mStatus == RUNNING)
|
||||
{
|
||||
mStatus = QUITTING;
|
||||
}
|
||||
mDataLock->unlock();
|
||||
wake();
|
||||
}
|
||||
|
||||
// static
|
||||
U32 LLThread::currentID()
|
||||
{
|
||||
return sThreadID;
|
||||
return sThreadID;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLThread::yield()
|
||||
{
|
||||
#if LL_LINUX || LL_SOLARIS
|
||||
sched_yield(); // annoyingly, apr_thread_yield is a noop on linux...
|
||||
sched_yield(); // annoyingly, apr_thread_yield is a noop on linux...
|
||||
#else
|
||||
apr_thread_yield();
|
||||
apr_thread_yield();
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLThread::wake()
|
||||
{
|
||||
mDataLock->lock();
|
||||
if(!shouldSleep())
|
||||
{
|
||||
mRunCondition->signal();
|
||||
}
|
||||
mDataLock->unlock();
|
||||
mDataLock->lock();
|
||||
if(!shouldSleep())
|
||||
{
|
||||
mRunCondition->signal();
|
||||
}
|
||||
mDataLock->unlock();
|
||||
}
|
||||
|
||||
void LLThread::wakeLocked()
|
||||
{
|
||||
if(!shouldSleep())
|
||||
{
|
||||
mRunCondition->signal();
|
||||
}
|
||||
if(!shouldSleep())
|
||||
{
|
||||
mRunCondition->signal();
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
@ -378,38 +425,38 @@ LLMutex* LLThreadSafeRefCount::sMutex = 0;
|
|||
//static
|
||||
void LLThreadSafeRefCount::initThreadSafeRefCount()
|
||||
{
|
||||
if (!sMutex)
|
||||
{
|
||||
sMutex = new LLMutex(0);
|
||||
}
|
||||
if (!sMutex)
|
||||
{
|
||||
sMutex = new LLMutex(0);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLThreadSafeRefCount::cleanupThreadSafeRefCount()
|
||||
{
|
||||
delete sMutex;
|
||||
sMutex = NULL;
|
||||
delete sMutex;
|
||||
sMutex = NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
LLThreadSafeRefCount::LLThreadSafeRefCount() :
|
||||
mRef(0)
|
||||
mRef(0)
|
||||
{
|
||||
}
|
||||
|
||||
LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)
|
||||
{
|
||||
mRef = 0;
|
||||
mRef = 0;
|
||||
}
|
||||
|
||||
LLThreadSafeRefCount::~LLThreadSafeRefCount()
|
||||
{
|
||||
if (mRef != 0)
|
||||
{
|
||||
LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
|
||||
}
|
||||
if (mRef != 0)
|
||||
{
|
||||
LL_ERRS() << "deleting non-zero reference" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
|
|||
|
|
@ -38,118 +38,120 @@ LL_COMMON_API void assert_main_thread();
|
|||
|
||||
namespace LLTrace
|
||||
{
|
||||
class ThreadRecorder;
|
||||
class ThreadRecorder;
|
||||
}
|
||||
|
||||
class LL_COMMON_API LLThread
|
||||
{
|
||||
private:
|
||||
friend class LLMutex;
|
||||
static U32 sIDIter;
|
||||
friend class LLMutex;
|
||||
static U32 sIDIter;
|
||||
|
||||
public:
|
||||
typedef enum e_thread_status
|
||||
{
|
||||
STOPPED = 0, // The thread is not running. Not started, or has exited its run function
|
||||
RUNNING = 1, // The thread is currently running
|
||||
QUITTING= 2 // Someone wants this thread to quit
|
||||
} EThreadStatus;
|
||||
typedef enum e_thread_status
|
||||
{
|
||||
STOPPED = 0, // The thread is not running. Not started, or has exited its run function
|
||||
RUNNING = 1, // The thread is currently running
|
||||
QUITTING= 2, // Someone wants this thread to quit
|
||||
CRASHED = -1 // An uncaught exception was thrown by the thread
|
||||
} EThreadStatus;
|
||||
|
||||
LLThread(const std::string& name, apr_pool_t *poolp = NULL);
|
||||
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
|
||||
virtual void shutdown(); // stops the thread
|
||||
|
||||
bool isQuitting() const { return (QUITTING == mStatus); }
|
||||
bool isStopped() const { return (STOPPED == mStatus); }
|
||||
|
||||
static U32 currentID(); // Return ID of current thread
|
||||
static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
|
||||
|
||||
LLThread(const std::string& name, apr_pool_t *poolp = NULL);
|
||||
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
|
||||
virtual void shutdown(); // stops the thread
|
||||
|
||||
bool isQuitting() const { return (QUITTING == mStatus); }
|
||||
bool isStopped() const { return (STOPPED == mStatus) || (CRASHED == mStatus); }
|
||||
bool isCrashed() const { return (CRASHED == mStatus); }
|
||||
|
||||
static U32 currentID(); // Return ID of current thread
|
||||
static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure.
|
||||
|
||||
public:
|
||||
// PAUSE / RESUME functionality. See source code for important usage notes.
|
||||
// Called from MAIN THREAD.
|
||||
void pause();
|
||||
void unpause();
|
||||
bool isPaused() { return isStopped() || mPaused == TRUE; }
|
||||
|
||||
// Cause the thread to wake up and check its condition
|
||||
void wake();
|
||||
// PAUSE / RESUME functionality. See source code for important usage notes.
|
||||
// Called from MAIN THREAD.
|
||||
void pause();
|
||||
void unpause();
|
||||
bool isPaused() { return isStopped() || mPaused == TRUE; }
|
||||
|
||||
// Cause the thread to wake up and check its condition
|
||||
void wake();
|
||||
|
||||
// Same as above, but to be used when the condition is already locked.
|
||||
void wakeLocked();
|
||||
// Same as above, but to be used when the condition is already locked.
|
||||
void wakeLocked();
|
||||
|
||||
// Called from run() (CHILD THREAD). Pause the thread if requested until unpaused.
|
||||
void checkPause();
|
||||
// Called from run() (CHILD THREAD). Pause the thread if requested until unpaused.
|
||||
void checkPause();
|
||||
|
||||
// this kicks off the apr thread
|
||||
void start(void);
|
||||
// this kicks off the apr thread
|
||||
void start(void);
|
||||
|
||||
apr_pool_t *getAPRPool() { return mAPRPoolp; }
|
||||
LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
|
||||
apr_pool_t *getAPRPool() { return mAPRPoolp; }
|
||||
LLVolatileAPRPool* getLocalAPRFilePool() { return mLocalAPRFilePoolp ; }
|
||||
|
||||
U32 getID() const { return mID; }
|
||||
U32 getID() const { return mID; }
|
||||
|
||||
// Called by threads *not* created via LLThread to register some
|
||||
// internal state used by LLMutex. You must call this once early
|
||||
// in the running thread to prevent collisions with the main thread.
|
||||
static void registerThreadID();
|
||||
|
||||
// Called by threads *not* created via LLThread to register some
|
||||
// internal state used by LLMutex. You must call this once early
|
||||
// in the running thread to prevent collisions with the main thread.
|
||||
static void registerThreadID();
|
||||
|
||||
private:
|
||||
BOOL mPaused;
|
||||
|
||||
// static function passed to APR thread creation routine
|
||||
static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap);
|
||||
BOOL mPaused;
|
||||
|
||||
// static function passed to APR thread creation routine
|
||||
static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap);
|
||||
|
||||
protected:
|
||||
std::string mName;
|
||||
class LLCondition* mRunCondition;
|
||||
LLMutex* mDataLock;
|
||||
std::string mName;
|
||||
class LLCondition* mRunCondition;
|
||||
LLMutex* mDataLock;
|
||||
|
||||
apr_thread_t *mAPRThreadp;
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
EThreadStatus mStatus;
|
||||
U32 mID;
|
||||
LLTrace::ThreadRecorder* mRecorder;
|
||||
apr_thread_t *mAPRThreadp;
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
EThreadStatus mStatus;
|
||||
U32 mID;
|
||||
LLTrace::ThreadRecorder* mRecorder;
|
||||
|
||||
//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
|
||||
//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
|
||||
// otherwise it will cause severe memory leaking!!! --bao
|
||||
LLVolatileAPRPool *mLocalAPRFilePoolp ;
|
||||
//a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used.
|
||||
//Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes.
|
||||
// otherwise it will cause severe memory leaking!!! --bao
|
||||
LLVolatileAPRPool *mLocalAPRFilePoolp ;
|
||||
|
||||
void setQuitting();
|
||||
|
||||
// virtual function overridden by subclass -- this will be called when the thread runs
|
||||
virtual void run(void) = 0;
|
||||
|
||||
// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
|
||||
virtual bool runCondition(void);
|
||||
void setQuitting();
|
||||
|
||||
// virtual function overridden by subclass -- this will be called when the thread runs
|
||||
virtual void run(void) = 0;
|
||||
|
||||
// virtual predicate function -- returns true if the thread should wake up, false if it should sleep.
|
||||
virtual bool runCondition(void);
|
||||
|
||||
// Lock/Unlock Run Condition -- use around modification of any variable used in runCondition()
|
||||
inline void lockData();
|
||||
inline void unlockData();
|
||||
|
||||
// This is the predicate that decides whether the thread should sleep.
|
||||
// It should only be called with mDataLock locked, since the virtual runCondition() function may need to access
|
||||
// data structures that are thread-unsafe.
|
||||
bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
|
||||
// Lock/Unlock Run Condition -- use around modification of any variable used in runCondition()
|
||||
inline void lockData();
|
||||
inline void unlockData();
|
||||
|
||||
// This is the predicate that decides whether the thread should sleep.
|
||||
// It should only be called with mDataLock locked, since the virtual runCondition() function may need to access
|
||||
// data structures that are thread-unsafe.
|
||||
bool shouldSleep(void) { return (mStatus == RUNNING) && (isPaused() || (!runCondition())); }
|
||||
|
||||
// To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following:
|
||||
// mDataLock->lock();
|
||||
// if(!shouldSleep())
|
||||
// mRunCondition->signal();
|
||||
// mDataLock->unlock();
|
||||
// To avoid spurious signals (and the associated context switches) when the condition may or may not have changed, you can do the following:
|
||||
// mDataLock->lock();
|
||||
// if(!shouldSleep())
|
||||
// mRunCondition->signal();
|
||||
// mDataLock->unlock();
|
||||
};
|
||||
|
||||
|
||||
void LLThread::lockData()
|
||||
{
|
||||
mDataLock->lock();
|
||||
mDataLock->lock();
|
||||
}
|
||||
|
||||
void LLThread::unlockData()
|
||||
{
|
||||
mDataLock->unlock();
|
||||
mDataLock->unlock();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -160,9 +162,9 @@ void LLThread::unlockData()
|
|||
class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
|
||||
{
|
||||
protected:
|
||||
virtual ~LLResponder();
|
||||
virtual ~LLResponder();
|
||||
public:
|
||||
virtual void completed(bool success) = 0;
|
||||
virtual void completed(bool success) = 0;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ set(llcorehttp_SOURCE_FILES
|
|||
httpoptions.cpp
|
||||
httprequest.cpp
|
||||
httpresponse.cpp
|
||||
httpstats.cpp
|
||||
_httplibcurl.cpp
|
||||
_httpopcancel.cpp
|
||||
_httpoperation.cpp
|
||||
|
|
@ -61,6 +62,7 @@ set(llcorehttp_HEADER_FILES
|
|||
httpoptions.h
|
||||
httprequest.h
|
||||
httpresponse.h
|
||||
httpstats.h
|
||||
_httpinternal.h
|
||||
_httplibcurl.h
|
||||
_httpopcancel.h
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@
|
|||
#include "llhttpconstants.h"
|
||||
#include "llproxy.h"
|
||||
|
||||
#include "httpstats.h"
|
||||
|
||||
// *DEBUG: "[curl:bugs] #1420" problem and testing.
|
||||
//
|
||||
// A pipelining problem, https://sourceforge.net/p/curl/bugs/1420/,
|
||||
|
|
@ -245,6 +247,8 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
|
|||
response->setHeaders(mReplyHeaders);
|
||||
response->setRequestURL(mReqURL);
|
||||
|
||||
response->setRequestMethod(methodToString(mReqMethod));
|
||||
|
||||
if (mReplyOffset || mReplyLength)
|
||||
{
|
||||
// Got an explicit offset/length in response
|
||||
|
|
@ -805,6 +809,7 @@ size_t HttpOpRequest::writeCallback(void * data, size_t size, size_t nmemb, void
|
|||
}
|
||||
const size_t req_size(size * nmemb);
|
||||
const size_t write_size(op->mReplyBody->append(static_cast<char *>(data), req_size));
|
||||
HTTPStats::instance().recordDataDown(write_size);
|
||||
return write_size;
|
||||
}
|
||||
|
||||
|
|
@ -833,7 +838,8 @@ size_t HttpOpRequest::readCallback(void * data, size_t size, size_t nmemb, void
|
|||
|
||||
const size_t do_size((std::min)(req_size, body_size - op->mCurlBodyPos));
|
||||
const size_t read_size(op->mReqBody->read(op->mCurlBodyPos, static_cast<char *>(data), do_size));
|
||||
op->mCurlBodyPos += read_size;
|
||||
HTTPStats::instance().recordDataUp(read_size);
|
||||
op->mCurlBodyPos += read_size;
|
||||
return read_size;
|
||||
}
|
||||
|
||||
|
|
@ -1145,6 +1151,25 @@ int HttpOpRequest::debugCallback(CURL * handle, curl_infotype info, char * buffe
|
|||
return 0;
|
||||
}
|
||||
|
||||
std::string HttpOpRequest::methodToString(const HttpOpRequest::EMethod &e)
|
||||
{
|
||||
if (e == HOR_COPY)
|
||||
return "COPY";
|
||||
else if (e == HOR_DELETE)
|
||||
return "DELETE";
|
||||
else if (e == HOR_GET)
|
||||
return "GET";
|
||||
else if (e == HOR_MOVE)
|
||||
return "MOVE";
|
||||
else if (e == HOR_PATCH)
|
||||
return "PATCH";
|
||||
else if (e == HOR_POST)
|
||||
return "POST";
|
||||
else if (e == HOR_PUT)
|
||||
return "PUT";
|
||||
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
} // end namespace LLCore
|
||||
|
||||
|
|
|
|||
|
|
@ -87,7 +87,8 @@ public:
|
|||
HOR_COPY,
|
||||
HOR_MOVE
|
||||
};
|
||||
|
||||
static std::string methodToString(const EMethod &);
|
||||
|
||||
virtual void stageFromRequest(HttpService *);
|
||||
virtual void stageFromReady(HttpService *);
|
||||
virtual void stageFromActive(HttpService *);
|
||||
|
|
@ -235,6 +236,7 @@ public:
|
|||
}; // end class HttpOpRequest
|
||||
|
||||
|
||||
|
||||
/// HttpOpRequestCompare isn't an operation but a uniform comparison
|
||||
/// functor for STL containers that order by priority. Mainly
|
||||
/// used for the ready queue container but defined here.
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "_httppolicyclass.h"
|
||||
|
||||
#include "lltimer.h"
|
||||
#include "httpstats.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -448,6 +449,8 @@ bool HttpPolicy::stageAfterCompletion(const HttpOpRequest::ptr_t &op)
|
|||
}
|
||||
|
||||
op->stageFromActive(mService);
|
||||
|
||||
HTTPStats::instance().recordResultCode(op->mStatus.getType());
|
||||
return false; // not active
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,8 @@
|
|||
|
||||
#include "lltimer.h"
|
||||
#include "llthread.h"
|
||||
|
||||
#include "llexception.h"
|
||||
#include "llmemory.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -293,22 +294,42 @@ void HttpService::threadRun(LLCoreInt::HttpThread * thread)
|
|||
ELoopSpeed loop(REQUEST_SLEEP);
|
||||
while (! mExitRequested)
|
||||
{
|
||||
loop = processRequestQueue(loop);
|
||||
try
|
||||
{
|
||||
loop = processRequestQueue(loop);
|
||||
|
||||
// Process ready queue issuing new requests as needed
|
||||
ELoopSpeed new_loop = mPolicy->processReadyQueue();
|
||||
loop = (std::min)(loop, new_loop);
|
||||
// Process ready queue issuing new requests as needed
|
||||
ELoopSpeed new_loop = mPolicy->processReadyQueue();
|
||||
loop = (std::min)(loop, new_loop);
|
||||
|
||||
// Give libcurl some cycles
|
||||
new_loop = mTransport->processTransport();
|
||||
loop = (std::min)(loop, new_loop);
|
||||
// Give libcurl some cycles
|
||||
new_loop = mTransport->processTransport();
|
||||
loop = (std::min)(loop, new_loop);
|
||||
|
||||
// Determine whether to spin, sleep briefly or sleep for next request
|
||||
if (REQUEST_SLEEP != loop)
|
||||
{
|
||||
ms_sleep(HTTP_SERVICE_LOOP_SLEEP_NORMAL_MS);
|
||||
}
|
||||
}
|
||||
// Determine whether to spin, sleep briefly or sleep for next request
|
||||
if (REQUEST_SLEEP != loop)
|
||||
{
|
||||
ms_sleep(HTTP_SERVICE_LOOP_SLEEP_NORMAL_MS);
|
||||
}
|
||||
}
|
||||
catch (const LLContinueError&)
|
||||
{
|
||||
LOG_UNHANDLED_EXCEPTION("");
|
||||
}
|
||||
catch (std::bad_alloc)
|
||||
{
|
||||
LLMemory::logMemoryInfo(TRUE);
|
||||
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print();
|
||||
|
||||
LL_ERRS() << "Bad memory allocation in HttpService::threadRun()!" << LL_ENDL;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
CRASH_ON_UNHANDLED_EXCEPTION("");
|
||||
}
|
||||
}
|
||||
|
||||
shutdown();
|
||||
sState = STOPPED;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
*/
|
||||
|
||||
#include "bufferarray.h"
|
||||
#include "llexception.h"
|
||||
#include "llmemory.h"
|
||||
|
||||
|
||||
// BufferArray is a list of chunks, each a BufferArray::Block, of contiguous
|
||||
|
|
@ -140,8 +142,22 @@ size_t BufferArray::append(const void * src, size_t len)
|
|||
{
|
||||
mBlocks.reserve(mBlocks.size() + 5);
|
||||
}
|
||||
Block * block = Block::alloc(BLOCK_ALLOC_SIZE);
|
||||
memcpy(block->mData, c_src, copy_len);
|
||||
Block * block;
|
||||
try
|
||||
{
|
||||
block = Block::alloc(BLOCK_ALLOC_SIZE);
|
||||
}
|
||||
catch (std::bad_alloc)
|
||||
{
|
||||
LLMemory::logMemoryInfo(TRUE);
|
||||
|
||||
//output possible call stacks to log file.
|
||||
LLError::LLCallStacks::print();
|
||||
|
||||
LL_WARNS() << "Bad memory allocation in thrown by Block::alloc in read!" << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
memcpy(block->mData, c_src, copy_len);
|
||||
block->mUsed = copy_len;
|
||||
llassert_always(block->mUsed <= block->mAlloced);
|
||||
mBlocks.push_back(block);
|
||||
|
|
@ -149,7 +165,7 @@ size_t BufferArray::append(const void * src, size_t len)
|
|||
c_src += copy_len;
|
||||
len -= copy_len;
|
||||
}
|
||||
return ret;
|
||||
return ret - len;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#include "_httpopsetget.h"
|
||||
|
||||
#include "lltimer.h"
|
||||
|
||||
#include "httpstats.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -62,6 +62,8 @@ HttpRequest::HttpRequest()
|
|||
mRequestQueue->addRef();
|
||||
|
||||
mReplyQueue.reset( new HttpReplyQueue() );
|
||||
|
||||
HTTPStats::instance().recordHTTPRequest();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -680,7 +680,7 @@ private:
|
|||
/// @}
|
||||
// End Global State
|
||||
// ====================================
|
||||
|
||||
|
||||
}; // end class HttpRequest
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -204,6 +204,15 @@ public:
|
|||
return mRequestUrl;
|
||||
}
|
||||
|
||||
void setRequestMethod(const std::string &method)
|
||||
{
|
||||
mRequestMethod = method;
|
||||
}
|
||||
|
||||
const std::string &getRequestMethod() const
|
||||
{
|
||||
return mRequestMethod;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Response data here
|
||||
|
|
@ -217,6 +226,7 @@ protected:
|
|||
unsigned int mRetries;
|
||||
unsigned int m503Retries;
|
||||
std::string mRequestUrl;
|
||||
std::string mRequestMethod;
|
||||
|
||||
TransferStats::ptr_t mStats;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* @file llviewerstats.cpp
|
||||
* @brief LLViewerStats class implementation
|
||||
*
|
||||
* $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 "httpstats.h"
|
||||
#include "llerror.h"
|
||||
|
||||
namespace LLCore
|
||||
{
|
||||
HTTPStats::HTTPStats()
|
||||
{
|
||||
resetStats();
|
||||
}
|
||||
|
||||
|
||||
HTTPStats::~HTTPStats()
|
||||
{
|
||||
}
|
||||
|
||||
void HTTPStats::resetStats()
|
||||
{
|
||||
mResutCodes.clear();
|
||||
mDataDown.reset();
|
||||
mDataUp.reset();
|
||||
mRequests = 0;
|
||||
}
|
||||
|
||||
|
||||
void HTTPStats::recordResultCode(S32 code)
|
||||
{
|
||||
std::map<S32, S32>::iterator it;
|
||||
|
||||
it = mResutCodes.find(code);
|
||||
|
||||
if (it == mResutCodes.end())
|
||||
mResutCodes[code] = 1;
|
||||
else
|
||||
(*it).second = (*it).second + 1;
|
||||
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string byte_count_converter(F32 bytes)
|
||||
{
|
||||
static const char unit_suffix[] = { 'B', 'K', 'M', 'G' };
|
||||
|
||||
F32 value = bytes;
|
||||
int suffix = 0;
|
||||
|
||||
while ((value > 1024.0) && (suffix < 3))
|
||||
{
|
||||
value /= 1024.0;
|
||||
++suffix;
|
||||
}
|
||||
|
||||
std::stringstream out;
|
||||
|
||||
out << std::setprecision(4) << value << unit_suffix[suffix];
|
||||
|
||||
return out.str();
|
||||
}
|
||||
}
|
||||
|
||||
void HTTPStats::dumpStats()
|
||||
{
|
||||
std::stringstream out;
|
||||
|
||||
out << "HTTP DATA SUMMARY" << std::endl;
|
||||
out << "HTTP Transfer counts:" << std::endl;
|
||||
out << "Data Sent: " << byte_count_converter(mDataUp.getSum()) << " (" << mDataUp.getSum() << ")" << std::endl;
|
||||
out << "Data Recv: " << byte_count_converter(mDataDown.getSum()) << " (" << mDataDown.getSum() << ")" << std::endl;
|
||||
out << "Total requests: " << mRequests << "(request objects created)" << std::endl;
|
||||
out << std::endl;
|
||||
out << "Result Codes:" << std::endl << "--- -----" << std::endl;
|
||||
|
||||
for (std::map<S32, S32>::iterator it = mResutCodes.begin(); it != mResutCodes.end(); ++it)
|
||||
{
|
||||
out << (*it).first << " " << (*it).second << std::endl;
|
||||
}
|
||||
|
||||
LL_WARNS("HTTP Core") << out.str() << LL_ENDL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* @file llviewerim_peningtats.h
|
||||
* @brief LLViewerStats class header file
|
||||
*
|
||||
* $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_LLVIEWERSTATS_H
|
||||
#define LL_LLVIEWERSTATS_H
|
||||
|
||||
#include "lltracerecording.h"
|
||||
#include "lltrace.h"
|
||||
#include "llstatsaccumulator.h"
|
||||
#include "llsingleton.h"
|
||||
#include "llsd.h"
|
||||
|
||||
namespace LLCore
|
||||
{
|
||||
class HTTPStats : public LLSingleton<HTTPStats>
|
||||
{
|
||||
LLSINGLETON(HTTPStats);
|
||||
virtual ~HTTPStats();
|
||||
|
||||
public:
|
||||
void resetStats();
|
||||
|
||||
typedef LLStatsAccumulator StatsAccumulator;
|
||||
|
||||
void recordDataDown(size_t bytes)
|
||||
{
|
||||
mDataDown.push(bytes);
|
||||
}
|
||||
|
||||
void recordDataUp(size_t bytes)
|
||||
{
|
||||
mDataUp.push(bytes);
|
||||
}
|
||||
|
||||
void recordHTTPRequest() { ++mRequests; }
|
||||
|
||||
void recordResultCode(S32 code);
|
||||
|
||||
void dumpStats();
|
||||
private:
|
||||
StatsAccumulator mDataDown;
|
||||
StatsAccumulator mDataUp;
|
||||
|
||||
S32 mRequests;
|
||||
|
||||
std::map<S32, S32> mResutCodes;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif // LL_LLVIEWERSTATS_H
|
||||
|
|
@ -215,7 +215,8 @@ void HttpRequestTestObjectType::test<1>()
|
|||
HttpRequest::destroyService();
|
||||
|
||||
// make sure we didn't leak any memory
|
||||
ensure("Memory returned", mMemTotal == GetMemTotal());
|
||||
// nat 2017-08-15 don't: requires total stasis in every other subsystem
|
||||
// ensure("Memory returned", mMemTotal == GetMemTotal());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ void logMessageSuccess(std::string logAuth, std::string url, std::string message
|
|||
|
||||
void logMessageFail(std::string logAuth, std::string url, std::string message)
|
||||
{
|
||||
LL_WARNS() << logAuth << " Failure '" << message << "' for " << url << LL_ENDL;
|
||||
LL_WARNS("CoreHTTP") << logAuth << " Failure '" << message << "' for " << url << LL_ENDL;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
|
|
@ -279,12 +279,10 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons
|
|||
result = LLSD::emptyMap();
|
||||
LLCore::HttpStatus::type_enum_t errType = status.getType();
|
||||
|
||||
LL_WARNS()
|
||||
<< "\n--------------------------------------------------------------------------\n"
|
||||
<< " Error[" << status.toTerseString() << "] cannot access url '" << response->getRequestURL()
|
||||
<< "' because " << status.toString()
|
||||
<< "\n--------------------------------------------------------------------------"
|
||||
<< LL_ENDL;
|
||||
LL_WARNS("CoreHTTP")
|
||||
<< " Error[" << status.toTerseString() << "] cannot "<< response->getRequestMethod()
|
||||
<< " to url '" << response->getRequestURL()
|
||||
<< "' because " << status.toString() << LL_ENDL;
|
||||
if ((errType >= 400) && (errType < 500))
|
||||
{
|
||||
LLSD body = this->parseBody(response, parseSuccess);
|
||||
|
|
@ -299,7 +297,6 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons
|
|||
result = body;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -323,7 +320,7 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons
|
|||
if (getBoolSetting(HTTP_LOGBODY_KEY))
|
||||
{
|
||||
// commenting out, but keeping since this can be useful for debugging
|
||||
LL_WARNS() << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL;
|
||||
LL_WARNS("CoreHTTP") << "Returned body=" << std::endl << httpStatus["error_body"].asString() << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -423,7 +420,7 @@ LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore:
|
|||
if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
|
||||
{
|
||||
std::string thebody = LLCoreHttpUtil::responseToString(response);
|
||||
LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
|
||||
LL_WARNS("CoreHTTP") << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
|
||||
<< " body: " << thebody << LL_ENDL;
|
||||
|
||||
// Replace the status with a new one indicating the failure.
|
||||
|
|
@ -442,7 +439,7 @@ LLSD HttpCoroLLSDHandler::handleSuccess(LLCore::HttpResponse * response, LLCore:
|
|||
if (contentType && (HTTP_CONTENT_LLSD_XML == *contentType))
|
||||
{
|
||||
std::string thebody = LLCoreHttpUtil::responseToString(response);
|
||||
LL_WARNS() << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
|
||||
LL_WARNS("CoreHTTP") << "Failed to deserialize . " << response->getRequestURL() << " [status:" << response->getStatus().toString() << "] "
|
||||
<< " body: " << thebody << LL_ENDL;
|
||||
|
||||
// Replace the status with a new one indicating the failure.
|
||||
|
|
@ -1210,7 +1207,7 @@ LLSD HttpCoroutineAdapter::buildImmediateErrorResult(const LLCore::HttpRequest::
|
|||
const std::string &url)
|
||||
{
|
||||
LLCore::HttpStatus status = request->getStatus();
|
||||
LL_WARNS() << "Error posting to " << url << " Status=" << status.getStatus() <<
|
||||
LL_WARNS("CoreHTTP") << "Error posting to " << url << " Status=" << status.getStatus() <<
|
||||
" message = " << status.getMessage() << LL_ENDL;
|
||||
|
||||
// Mimic the status results returned from an http error that we had
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include <curl/curl.h>
|
||||
|
||||
#include "llcorehttputil.h"
|
||||
#include "httpstats.h"
|
||||
|
||||
#ifdef OPENSIM
|
||||
#include "llviewernetwork.h"
|
||||
|
|
@ -317,6 +318,8 @@ void LLAppCoreHttp::requestStop()
|
|||
|
||||
void LLAppCoreHttp::cleanup()
|
||||
{
|
||||
LLCore::HTTPStats::instance().dumpStats();
|
||||
|
||||
if (LLCORE_HTTP_HANDLE_INVALID == mStopHandle)
|
||||
{
|
||||
// Should have been started already...
|
||||
|
|
|
|||
|
|
@ -1286,6 +1286,19 @@ bool LLAppViewer::init()
|
|||
}
|
||||
}
|
||||
|
||||
char* PARENT = getenv("PARENT");
|
||||
if (! (PARENT && std::string(PARENT) == "SL_Launcher"))
|
||||
{
|
||||
// Don't directly run this executable. Please run the launcher, which
|
||||
// will run the viewer itself.
|
||||
// Naturally we do not consider this bulletproof. The point is to
|
||||
// gently remind a user who *inadvertently* finds him/herself in this
|
||||
// situation to do things the Right Way. Anyone who intentionally
|
||||
// bypasses this mechanism needs no reminder that s/he's shooting
|
||||
// him/herself in the foot.
|
||||
LLNotificationsUtil::add("RunLauncher");
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion())
|
||||
{
|
||||
|
|
@ -4093,6 +4106,7 @@ void LLAppViewer::writeSystemInfo()
|
|||
gDebugInfo["ClientInfo"]["MinorVersion"] = LLVersionInfo::getMinor();
|
||||
gDebugInfo["ClientInfo"]["PatchVersion"] = LLVersionInfo::getPatch();
|
||||
gDebugInfo["ClientInfo"]["BuildVersion"] = LLVersionInfo::getBuild();
|
||||
gDebugInfo["ClientInfo"]["AddressSize"] = LLVersionInfo::getAddressSize();
|
||||
|
||||
// <FS:ND> Add which flavor of FS generated an error
|
||||
#ifdef OPENSIM
|
||||
|
|
|
|||
|
|
@ -852,13 +852,13 @@ LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is)
|
|||
for(stats_map_t::iterator it = time_stats.begin(); it != time_stats.end(); ++it)
|
||||
{
|
||||
std::string label = it->first;
|
||||
ret[label]["TotalTime"] = time_stats[label].mSum;
|
||||
ret[label]["TotalTime"] = time_stats[label].getSum();
|
||||
ret[label]["MeanTime"] = time_stats[label].getMean();
|
||||
ret[label]["MaxTime"] = time_stats[label].getMaxValue();
|
||||
ret[label]["MinTime"] = time_stats[label].getMinValue();
|
||||
ret[label]["StdDevTime"] = time_stats[label].getStdDev();
|
||||
|
||||
ret[label]["Samples"] = sample_stats[label].mSum;
|
||||
ret[label]["Samples"] = sample_stats[label].getSum();
|
||||
ret[label]["MaxSamples"] = sample_stats[label].getMaxValue();
|
||||
ret[label]["MinSamples"] = sample_stats[label].getMinValue();
|
||||
ret[label]["StdDevSamples"] = sample_stats[label].getStdDev();
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
// llcommon
|
||||
#include "llevents.h"
|
||||
#include "stringize.h"
|
||||
#include "llsdserialize.h"
|
||||
|
||||
// llmessage (!)
|
||||
#include "llfiltersd2xmlrpc.h" // for xml_escape_string()
|
||||
|
|
@ -47,12 +48,10 @@
|
|||
#include "llstartup.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llnotifications.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llwindow.h"
|
||||
#include "llviewerwindow.h"
|
||||
#include "llprogressview.h"
|
||||
#if LL_LINUX
|
||||
#include "lltrans.h"
|
||||
#endif
|
||||
#include "llsecapi.h"
|
||||
#include "llstartup.h"
|
||||
#include "llmachineid.h"
|
||||
|
|
@ -265,62 +264,89 @@ bool LLLoginInstance::handleLoginEvent(const LLSD& event)
|
|||
|
||||
void LLLoginInstance::handleLoginFailure(const LLSD& event)
|
||||
{
|
||||
|
||||
// Login has failed.
|
||||
// Figure out why and respond...
|
||||
LLSD response = event["data"];
|
||||
std::string reason_response = response["reason"].asString();
|
||||
std::string message_response = response["message"].asString();
|
||||
// For the cases of critical message or TOS agreement,
|
||||
// start the TOS dialog. The dialog response will be handled
|
||||
// by the LLLoginInstance::handleTOSResponse() callback.
|
||||
// The callback intiates the login attempt next step, either
|
||||
// to reconnect or to end the attempt in failure.
|
||||
if(reason_response == "tos")
|
||||
{
|
||||
LL_INFOS() << "LLLoginInstance::handleLoginFailure ToS" << LL_ENDL;
|
||||
|
||||
// Login has failed.
|
||||
// Figure out why and respond...
|
||||
LLSD response = event["data"];
|
||||
std::string reason_response = response["reason"].asString();
|
||||
std::string message_response = response["message"].asString();
|
||||
// For the cases of critical message or TOS agreement,
|
||||
// start the TOS dialog. The dialog response will be handled
|
||||
// by the LLLoginInstance::handleTOSResponse() callback.
|
||||
// The callback intiates the login attempt next step, either
|
||||
// to reconnect or to end the attempt in failure.
|
||||
if(reason_response == "tos")
|
||||
{
|
||||
LL_INFOS() << "LLLoginInstance::handleLoginFailure ToS" << LL_ENDL;
|
||||
LLSD data(LLSD::emptyMap());
|
||||
data["message"] = message_response;
|
||||
data["reply_pump"] = TOS_REPLY_PUMP;
|
||||
if (gViewerWindow)
|
||||
gViewerWindow->setShowProgress(FALSE, FALSE);
|
||||
LLFloaterReg::showInstance("message_tos", data);
|
||||
LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
|
||||
.listen(TOS_LISTENER_NAME,
|
||||
boost::bind(&LLLoginInstance::handleTOSResponse,
|
||||
this, _1, "agree_to_tos"));
|
||||
}
|
||||
else if(reason_response == "critical")
|
||||
{
|
||||
LL_INFOS() << "LLLoginInstance::handleLoginFailure Crit" << LL_ENDL;
|
||||
|
||||
LLSD data(LLSD::emptyMap());
|
||||
data["message"] = message_response;
|
||||
data["reply_pump"] = TOS_REPLY_PUMP;
|
||||
if (gViewerWindow)
|
||||
gViewerWindow->setShowProgress(FALSE,FALSE);
|
||||
LLFloaterReg::showInstance("message_tos", data);
|
||||
LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
|
||||
.listen(TOS_LISTENER_NAME,
|
||||
boost::bind(&LLLoginInstance::handleTOSResponse,
|
||||
this, _1, "agree_to_tos"));
|
||||
}
|
||||
else if(reason_response == "critical")
|
||||
{
|
||||
LL_INFOS() << "LLLoginInstance::handleLoginFailure Crit" << LL_ENDL;
|
||||
LLSD data(LLSD::emptyMap());
|
||||
data["message"] = message_response;
|
||||
data["reply_pump"] = TOS_REPLY_PUMP;
|
||||
if(response.has("error_code"))
|
||||
{
|
||||
data["error_code"] = response["error_code"];
|
||||
}
|
||||
if(response.has("certificate"))
|
||||
{
|
||||
data["certificate"] = response["certificate"];
|
||||
}
|
||||
|
||||
if (gViewerWindow)
|
||||
gViewerWindow->setShowProgress(FALSE, FALSE);
|
||||
LLFloaterReg::showInstance("message_critical", data);
|
||||
LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
|
||||
.listen(TOS_LISTENER_NAME,
|
||||
boost::bind(&LLLoginInstance::handleTOSResponse,
|
||||
this, _1, "read_critical"));
|
||||
}
|
||||
else if(reason_response == "update")
|
||||
{
|
||||
// This shouldn't happen - the viewer manager should have forced an update;
|
||||
// possibly the user ran the viewer directly and bypassed the update check
|
||||
std::string required_version = response["message_args"]["VERSION"];
|
||||
LL_WARNS() << "Login failed because an update to version " << required_version << " is required." << LL_ENDL;
|
||||
|
||||
LLSD data(LLSD::emptyMap());
|
||||
data["message"] = message_response;
|
||||
data["reply_pump"] = TOS_REPLY_PUMP;
|
||||
if(response.has("error_code"))
|
||||
{
|
||||
data["error_code"] = response["error_code"];
|
||||
}
|
||||
if(response.has("certificate"))
|
||||
{
|
||||
data["certificate"] = response["certificate"];
|
||||
}
|
||||
|
||||
if (gViewerWindow)
|
||||
gViewerWindow->setShowProgress(FALSE,FALSE);
|
||||
LLFloaterReg::showInstance("message_critical", data);
|
||||
LLEventPumps::instance().obtain(TOS_REPLY_PUMP)
|
||||
.listen(TOS_LISTENER_NAME,
|
||||
boost::bind(&LLLoginInstance::handleTOSResponse,
|
||||
this, _1, "read_critical"));
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "LLLoginInstance::handleLoginFailure attemptComplete" << LL_ENDL;
|
||||
attemptComplete();
|
||||
}
|
||||
if (gViewerWindow)
|
||||
gViewerWindow->setShowProgress(FALSE, FALSE);
|
||||
|
||||
LLSD data(LLSD::emptyMap());
|
||||
data["VERSION"] = required_version;
|
||||
LLNotificationsUtil::add("RequiredUpdate", data, LLSD::emptyMap(), boost::bind(&LLLoginInstance::handleLoginDisallowed, this, _1, _2));
|
||||
}
|
||||
else if(reason_response == "key")
|
||||
{
|
||||
// this is a password problem or other restriction
|
||||
// an appropriate message has already been displayed
|
||||
attemptComplete();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Login failed for an unknown reason: " << LLSDOStreamer<LLSDNotationFormatter>(response) << LL_ENDL;
|
||||
|
||||
if (gViewerWindow)
|
||||
gViewerWindow->setShowProgress(FALSE, FALSE);
|
||||
|
||||
LLNotificationsUtil::add("LoginFailedUnknown", LLSD::emptyMap(), LLSD::emptyMap(), boost::bind(&LLLoginInstance::handleLoginDisallowed, this, _1, _2));
|
||||
}
|
||||
}
|
||||
|
||||
void LLLoginInstance::handleLoginDisallowed(const LLSD& notification, const LLSD& response)
|
||||
{
|
||||
attemptComplete();
|
||||
}
|
||||
|
||||
void LLLoginInstance::handleLoginSuccess(const LLSD& event)
|
||||
|
|
@ -377,6 +403,7 @@ bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string construct_start_string()
|
||||
{
|
||||
std::string start;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ private:
|
|||
void handleLoginSuccess(const LLSD& event);
|
||||
void handleDisconnect(const LLSD& event);
|
||||
void handleIndeterminate(const LLSD& event);
|
||||
void handleLoginDisallowed(const LLSD& notification, const LLSD& response);
|
||||
|
||||
bool handleTOSResponse(bool v, const std::string& key);
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@ public:
|
|||
static const std::string& getBuildPlatform();
|
||||
// [/SL:KB]
|
||||
|
||||
/// return the bit width of an address
|
||||
static const S32 getAddressSize() { return ADDRESS_SIZE; }
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TEST_VIEWER,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include "lltextureinfo.h"
|
||||
#include "lltracerecording.h"
|
||||
#include "lltrace.h"
|
||||
|
||||
#include "llstatsaccumulator.h"
|
||||
|
||||
enum ESimStatID
|
||||
{
|
||||
|
|
@ -261,91 +261,9 @@ public:
|
|||
|
||||
void addToMessage(LLSD &body);
|
||||
|
||||
struct StatsAccumulator
|
||||
{
|
||||
S32 mCount;
|
||||
F32 mSum;
|
||||
F32 mSumOfSquares;
|
||||
F32 mMinValue;
|
||||
F32 mMaxValue;
|
||||
U32 mCountOfNextUpdatesToIgnore;
|
||||
typedef LLStatsAccumulator StatsAccumulator;
|
||||
|
||||
inline StatsAccumulator()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
inline void push( F32 val )
|
||||
{
|
||||
if ( mCountOfNextUpdatesToIgnore > 0 )
|
||||
{
|
||||
mCountOfNextUpdatesToIgnore--;
|
||||
return;
|
||||
}
|
||||
|
||||
mCount++;
|
||||
mSum += val;
|
||||
mSumOfSquares += val * val;
|
||||
if (mCount == 1 || val > mMaxValue)
|
||||
{
|
||||
mMaxValue = val;
|
||||
}
|
||||
if (mCount == 1 || val < mMinValue)
|
||||
{
|
||||
mMinValue = val;
|
||||
}
|
||||
}
|
||||
|
||||
inline F32 getMean() const
|
||||
{
|
||||
return (mCount == 0) ? 0.f : ((F32)mSum)/mCount;
|
||||
}
|
||||
|
||||
inline F32 getMinValue() const
|
||||
{
|
||||
return mMinValue;
|
||||
}
|
||||
|
||||
inline F32 getMaxValue() const
|
||||
{
|
||||
return mMaxValue;
|
||||
}
|
||||
|
||||
inline F32 getStdDev() const
|
||||
{
|
||||
const F32 mean = getMean();
|
||||
// <FS:CR> Fix implicit conversion double to float
|
||||
//return (mCount < 2) ? 0.f : sqrt(llmax(0.f,mSumOfSquares/mCount - (mean * mean)));
|
||||
return (mCount < 2) ? 0.f : sqrtf(llmax(0.f,mSumOfSquares/mCount - (mean * mean)));
|
||||
}
|
||||
|
||||
inline U32 getCount() const
|
||||
{
|
||||
return mCount;
|
||||
}
|
||||
|
||||
inline void reset()
|
||||
{
|
||||
mCount = 0;
|
||||
mSum = mSumOfSquares = 0.f;
|
||||
mMinValue = 0.0f;
|
||||
mMaxValue = 0.0f;
|
||||
mCountOfNextUpdatesToIgnore = 0;
|
||||
}
|
||||
|
||||
inline LLSD asLLSD() const
|
||||
{
|
||||
LLSD data;
|
||||
data["mean"] = getMean();
|
||||
data["std_dev"] = getStdDev();
|
||||
data["count"] = (S32)mCount;
|
||||
data["min"] = getMinValue();
|
||||
data["max"] = getMaxValue();
|
||||
return data;
|
||||
}
|
||||
};
|
||||
|
||||
// Phase tracking (originally put in for avatar rezzing), tracking
|
||||
// Phase tracking (originally put in for avatar rezzing), tracking
|
||||
// progress of active/completed phases for activities like outfit changing.
|
||||
typedef std::map<std::string,LLTimer> phase_map_t;
|
||||
typedef std::map<std::string,StatsAccumulator> phase_stats_t;
|
||||
|
|
|
|||
|
|
@ -1795,6 +1795,13 @@ Visit [_URL] for more information?
|
|||
<tag>fail</tag>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="RunLauncher"
|
||||
type="alertmodal">
|
||||
Please do not directly run the viewer executable. Update any existing shortcuts to run SL_Launcher instead.
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="OldGPUDriver"
|
||||
|
|
@ -3942,143 +3949,12 @@ Finished download of raw terrain file to:
|
|||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DownloadWindowsMandatory"
|
||||
name="RequiredUpdate"
|
||||
type="alertmodal">
|
||||
A new version of [APP_NAME] is available.
|
||||
[MESSAGE]
|
||||
You must download this update to use [APP_NAME].
|
||||
Version [VERSION] is required for login.
|
||||
This should have been updated for you but apparently was not.
|
||||
Please download from https://secondlife.com/support/downloads/
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Quit"
|
||||
yestext="Download"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DownloadWindows"
|
||||
type="alertmodal">
|
||||
An updated version of [APP_NAME] is available.
|
||||
[MESSAGE]
|
||||
This update is not required, but we suggest you install it to improve performance and stability.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Continue"
|
||||
yestext="Download"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DownloadWindowsReleaseForDownload"
|
||||
type="alertmodal">
|
||||
An updated version of [APP_NAME] is available.
|
||||
[MESSAGE]
|
||||
This update is not required, but we suggest you install it to improve performance and stability.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Continue"
|
||||
yestext="Download"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DownloadLinuxMandatory"
|
||||
type="alertmodal">
|
||||
A new version of [APP_NAME] is available.
|
||||
[MESSAGE]
|
||||
You must download this update to use [APP_NAME].
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Quit"
|
||||
yestext="Download"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DownloadLinux"
|
||||
type="alertmodal">
|
||||
An updated version of [APP_NAME] is available.
|
||||
[MESSAGE]
|
||||
This update is not required, but we suggest you install it to improve performance and stability.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Continue"
|
||||
yestext="Download"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DownloadLinuxReleaseForDownload"
|
||||
type="alertmodal">
|
||||
An updated version of [APP_NAME] is available.
|
||||
[MESSAGE]
|
||||
This update is not required, but we suggest you install it to improve performance and stability.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Continue"
|
||||
yestext="Download"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DownloadMacMandatory"
|
||||
type="alertmodal">
|
||||
A new version of [APP_NAME] is available.
|
||||
[MESSAGE]
|
||||
You must download this update to use [APP_NAME].
|
||||
|
||||
Download to your Applications folder?
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Quit"
|
||||
yestext="Download"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DownloadMac"
|
||||
type="alertmodal">
|
||||
An updated version of [APP_NAME] is available.
|
||||
[MESSAGE]
|
||||
This update is not required, but we suggest you install it to improve performance and stability.
|
||||
|
||||
Download to your Applications folder?
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Continue"
|
||||
yestext="Download"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DownloadMacReleaseForDownload"
|
||||
type="alertmodal">
|
||||
An updated version of [APP_NAME] is available.
|
||||
[MESSAGE]
|
||||
This update is not required, but we suggest you install it to improve performance and stability.
|
||||
|
||||
Download to your Applications folder?
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Continue"
|
||||
yestext="Download"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="FailedUpdateInstall"
|
||||
type="alertmodal">
|
||||
An error occurred installing the viewer update.
|
||||
Please download and install the latest viewer from
|
||||
http://secondlife.com/download.
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
|
|
@ -4086,195 +3962,16 @@ http://secondlife.com/download.
|
|||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="FailedRequiredUpdateInstall"
|
||||
name="LoginFailedUnknown"
|
||||
type="alertmodal">
|
||||
We were unable to install a required update.
|
||||
You will be unable to log in until [APP_NAME] has been updated.
|
||||
|
||||
Please download and install the latest viewer from
|
||||
http://secondlife.com/download.
|
||||
<tag>fail</tag>
|
||||
Sorry, login failed for an unrecognized reason.
|
||||
If you continue to get this message, please check the [SUPPORT_SITE].
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="Quit"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="UpdaterServiceNotRunning"
|
||||
type="alertmodal">
|
||||
There is a required update for your Second Life Installation.
|
||||
|
||||
You may download this update from http://www.secondlife.com/downloads
|
||||
or you can install it now.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Quit Second Life"
|
||||
yestext="Download and install now"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notify.tga"
|
||||
name="DownloadBackgroundTip"
|
||||
type="notify">
|
||||
We have downloaded an update to your [APP_NAME] installation.
|
||||
Version [VERSION] [[INFO_URL] Information about this update]
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Later..."
|
||||
yestext="Install now and restart [APP_NAME]"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DownloadBackgroundDialog"
|
||||
type="alertmodal">
|
||||
We have downloaded an update to your [APP_NAME] installation.
|
||||
Version [VERSION] [[INFO_URL] Information about this update]
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Later..."
|
||||
yestext="Install now and restart [APP_NAME]"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="RequiredUpdateDownloadedVerboseDialog"
|
||||
type="alertmodal"
|
||||
force_urls_external="true">
|
||||
We have downloaded a required software update.
|
||||
Version [VERSION] [[INFO_URL] Information about this update]
|
||||
|
||||
We must restart [APP_NAME] to install the update.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="RequiredUpdateDownloadedDialog"
|
||||
type="alertmodal"
|
||||
force_urls_external="true">
|
||||
We must restart [APP_NAME] to install the update.
|
||||
[[INFO_URL] Information about this update]
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="notify.tga"
|
||||
name="OtherChannelDownloadBackgroundTip"
|
||||
type="notify">
|
||||
We have downloaded an update to your [APP_NAME] installation.
|
||||
Version [VERSION]
|
||||
This experimental viewer has been replaced by a [NEW_CHANNEL] viewer;
|
||||
see [[INFO_URL] for details about this update]
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Later..."
|
||||
yestext="Install now and restart [APP_NAME]"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="OtherChannelDownloadBackgroundDialog"
|
||||
type="alertmodal">
|
||||
We have downloaded an update to your [APP_NAME] installation.
|
||||
Version [VERSION]
|
||||
This experimental viewer has been replaced by a [NEW_CHANNEL] viewer;
|
||||
see [[INFO_URL] Information about this update]
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okcancelbuttons"
|
||||
notext="Later..."
|
||||
yestext="Install now and restart [APP_NAME]"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="OtherChannelRequiredUpdateDownloadedVerboseDialog"
|
||||
type="alertmodal"
|
||||
force_urls_external="true">
|
||||
We have downloaded a required software update.
|
||||
Version [VERSION]
|
||||
This experimental viewer has been replaced by a [NEW_CHANNEL] viewer;
|
||||
see [[INFO_URL] Information about this update]
|
||||
|
||||
We must restart [APP_NAME] to install the update.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="OtherChannelRequiredUpdateDownloadedDialog"
|
||||
type="alertmodal"
|
||||
force_urls_external="true">
|
||||
We must restart [APP_NAME] to install the update.
|
||||
This experimental viewer has been replaced by a [NEW_CHANNEL] viewer;
|
||||
see [[INFO_URL] Information about this update]
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="UpdateDownloadInProgress"
|
||||
type="alertmodal">
|
||||
An update is available!
|
||||
It's downloading in the background and we will prompt you to restart your viewer to finish installing it as soon as it's ready.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="UpdateDownloadComplete"
|
||||
type="alertmodal">
|
||||
An update was downloaded. It will be installed during restart.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="UpdateDeferred"
|
||||
type="alertmodal">
|
||||
An update was downloaded that you previously chose to skip or defer to the next start up.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="UpdateViewerUpToDate"
|
||||
type="alertmodal">
|
||||
Your viewer is up to date!
|
||||
If you can't wait to try out the latest features and fixes, check out the Alternate Viewers page. http://wiki.secondlife.com/wiki/Linden_Lab_Official:Alternate_Viewers.
|
||||
<tag>confirm</tag>
|
||||
<usetemplate
|
||||
name="okbutton"
|
||||
yestext="OK"/>
|
||||
</notification>
|
||||
|
||||
<notification
|
||||
icon="alertmodal.tga"
|
||||
name="DeedObjectToGroup"
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
// other Linden headers
|
||||
#include "../test/lltut.h"
|
||||
#include "llevents.h"
|
||||
#include "llnotificationsutil.h"
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
#pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr
|
||||
|
|
@ -112,6 +113,19 @@ void LLCredential::authenticatorType(std::string &idType)
|
|||
{
|
||||
}
|
||||
|
||||
LLNotificationPtr LLNotificationsUtil::add(const std::string& name,
|
||||
const LLSD& substitutions,
|
||||
const LLSD& payload,
|
||||
boost::function<void (const LLSD&, const LLSD&)> functor)
|
||||
{
|
||||
return LLNotificationPtr((LLNotification*)NULL);
|
||||
}
|
||||
|
||||
LLNotificationPtr LLNotificationsUtil::add(const std::string& name, const LLSD& args)
|
||||
{
|
||||
return LLNotificationPtr((LLNotification*)NULL);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "../llviewernetwork.h"
|
||||
LLGridManager::~LLGridManager()
|
||||
|
|
|
|||
|
|
@ -1346,6 +1346,18 @@ class DarwinManifest(ViewerManifest):
|
|||
keychain_pwd_path = os.path.join(build_secrets_checkout,'code-signing-osx','password.txt')
|
||||
keychain_pwd = open(keychain_pwd_path).read().rstrip()
|
||||
|
||||
# Note: As of macOS Sierra, keychains are created with names postfixed with '-db' so for example, the
|
||||
# SL Viewer keychain would by default be found in ~/Library/Keychains/viewer.keychain-db instead of
|
||||
# just ~/Library/Keychains/viewer.keychain in earlier versions.
|
||||
#
|
||||
# Because we have old OS files from previous versions of macOS on the build hosts, the configurations
|
||||
# are different on each host. Some have viewer.keychain, some have viewer.keychain-db and some have both.
|
||||
# As you can see in the line below, this script expects the Linden Developer cert/keys to be in viewer.keychain.
|
||||
#
|
||||
# To correctly sign builds you need to make sure ~/Library/Keychains/viewer.keychain exists on the host
|
||||
# and that it contains the correct cert/key. If a build host is set up with a clean version of macOS Sierra (or later)
|
||||
# then you will need to change this line (and the one for 'codesign' command below) to point to right place or else
|
||||
# pull in the cert/key into the default viewer keychain 'viewer.keychain-db' and export it to 'viewer.keychain'
|
||||
self.run_command('security unlock-keychain -p "%s" "%s/Library/Keychains/viewer.keychain"' % ( keychain_pwd, home_path ) )
|
||||
signed=False
|
||||
sign_attempts=3
|
||||
|
|
@ -1354,6 +1366,7 @@ class DarwinManifest(ViewerManifest):
|
|||
try:
|
||||
sign_attempts-=1;
|
||||
self.run_command(
|
||||
# Note: See blurb above about names of keychains
|
||||
'codesign --verbose --deep --force --keychain "%(home_path)s/Library/Keychains/viewer.keychain" --sign %(identity)r %(bundle)r' % {
|
||||
'home_path' : home_path,
|
||||
'identity': identity,
|
||||
|
|
|
|||
Loading…
Reference in New Issue