diff options
Diffstat (limited to 'indra')
| -rwxr-xr-x | indra/llcommon/CMakeLists.txt | 3 | ||||
| -rw-r--r-- | indra/llcommon/lldeadmantimer.cpp | 36 | ||||
| -rw-r--r-- | indra/llcommon/lldeadmantimer.h | 38 | ||||
| -rw-r--r-- | indra/llcommon/llprocinfo.cpp | 94 | ||||
| -rw-r--r-- | indra/llcommon/llprocinfo.h | 68 | ||||
| -rw-r--r-- | indra/llcommon/tests/lldeadmantimer_test.cpp | 692 | ||||
| -rw-r--r-- | indra/llcommon/tests/llprocinfo_test.cpp | 91 | ||||
| -rwxr-xr-x | indra/newview/llappcorehttp.cpp | 3 | ||||
| -rwxr-xr-x | indra/newview/llmeshrepository.cpp | 804 | 
9 files changed, 914 insertions, 915 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index af7a9aa3a6..ce62a1978d 100755 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -80,6 +80,7 @@ set(llcommon_SOURCE_FILES      llptrto.cpp       llprocess.cpp      llprocessor.cpp +    llprocinfo.cpp      llqueuedthread.cpp      llrand.cpp      llrefcount.cpp @@ -208,6 +209,7 @@ set(llcommon_HEADER_FILES      llpriqueuemap.h      llprocess.h      llprocessor.h +    llprocinfo.h      llptrskiplist.h      llptrskipmap.h      llptrto.h @@ -331,6 +333,7 @@ if (LL_TESTS)    LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}") +  LL_ADD_INTEGRATION_TEST(llprocinfo "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llsingleton "" "${test_libs}")                           diff --git a/indra/llcommon/lldeadmantimer.cpp b/indra/llcommon/lldeadmantimer.cpp index 2a356d857a..7d9097e344 100644 --- a/indra/llcommon/lldeadmantimer.cpp +++ b/indra/llcommon/lldeadmantimer.cpp @@ -42,14 +42,19 @@  //   false    true   Timer finished, result can be read once  //    true    true   Not allowed  // -LLDeadmanTimer::LLDeadmanTimer(F64 horizon) +LLDeadmanTimer::LLDeadmanTimer(F64 horizon, bool inc_cpu)  	: mHorizon(time_type(llmax(horizon, F64(0.0)) * gClockFrequency)),  	  mActive(false),			// If true, a timer is running.  	  mDone(false),				// If true, timer has completed and can be read (once)  	  mStarted(U64L(0)),  	  mExpires(U64L(0)),  	  mStopped(U64L(0)), -	  mCount(U64L(0)) +	  mCount(U64L(0)), +	  mIncCPU(inc_cpu), +	  mUStartCPU(LLProcInfo::time_type(U64L(0))), +	  mUEndCPU(LLProcInfo::time_type(U64L(0))), +	  mSStartCPU(LLProcInfo::time_type(U64L(0))), +	  mSEndCPU(LLProcInfo::time_type(U64L(0)))  {} @@ -76,6 +81,10 @@ void LLDeadmanTimer::start(time_type now)  	mExpires = now + mHorizon;  	mStopped = now;  	mCount = U64L(0); +	if (mIncCPU) +	{ +		LLProcInfo::getCPUUsage(mUStartCPU, mSStartCPU); +	}  } @@ -93,9 +102,26 @@ void LLDeadmanTimer::stop(time_type now)  	mStopped = now;  	mActive = false;  	mDone = true; +	if (mIncCPU) +	{ +		LLProcInfo::getCPUUsage(mUEndCPU, mSEndCPU); +	}  } +bool LLDeadmanTimer::isExpired(time_type now, F64 & started, F64 & stopped, U64 & count, +							   U64 & user_cpu, U64 & sys_cpu) +{ +	const bool status(isExpired(now, started, stopped, count)); +	if (status) +	{ +		user_cpu = U64(mUEndCPU - mUStartCPU); +		sys_cpu = U64(mSEndCPU - mSStartCPU); +	} +	return status; +} + +		  bool LLDeadmanTimer::isExpired(time_type now, F64 & started, F64 & stopped, U64 & count)  {  	if (mActive && ! mDone) @@ -141,14 +167,20 @@ void LLDeadmanTimer::ringBell(time_type now, unsigned int count)  	if (now >= mExpires)  	{ +		// Timer has expired, this event will be dropped  		mActive = false;  		mDone = true;  	}  	else  	{ +		// Timer renewed, keep going  		mStopped = now;  		mExpires = now + mHorizon;  		mCount += count; +		if (mIncCPU) +		{ +			LLProcInfo::getCPUUsage(mUEndCPU, mSEndCPU); +		}  	}  	return; diff --git a/indra/llcommon/lldeadmantimer.h b/indra/llcommon/lldeadmantimer.h index 8643b8cad8..0dde16b717 100644 --- a/indra/llcommon/lldeadmantimer.h +++ b/indra/llcommon/lldeadmantimer.h @@ -32,6 +32,7 @@  #include "linden_common.h"  #include "lltimer.h" +#include "llprocinfo.h"  /// @file lldeadmantimer.h @@ -93,7 +94,11 @@ public:  	///                 call at which point the timer will consider itself  	///					expired.  	/// -	LLDeadmanTimer(F64 horizon); +	/// @param inc_cpu	If true, gather system and user cpu stats while +	///					running the timer.  This does require more syscalls +	///					during updates.  If false, cpu usage data isn't +	///					collected and will be zero if queried. +	LLDeadmanTimer(F64 horizon, bool inc_cpu);  	~LLDeadmanTimer()   		{} @@ -173,21 +178,38 @@ public:  	/// @param count	If expired, the number of ringBell() calls  	///					made prior to expiration.  	/// +	/// @param user_cpu	Amount of CPU spent in user mode by the process +	///					during the event.  Value in microseconds and will +	///					read zero if not enabled by the constructor. +	/// +	/// @param sys_cpu	Amount of CPU spent in system mode by the process. +	///  	/// @return			true if the timer has expired, false otherwise.  	///					If true, it also returns the started,  	///					stopped and count values otherwise these are  	///					left unchanged.  	/// +	bool isExpired(time_type now, F64 & started, F64 & stopped, U64 & count, +				   U64 & user_cpu, U64 & sys_cpu); + +	/// Identical to the six-arugment form except is does without the +	/// CPU time return if the caller isn't interested in it.  	bool isExpired(time_type now, F64 & started, F64 & stopped, U64 & count);  protected: -	time_type	mHorizon; -	bool		mActive; -	bool		mDone; -	time_type	mStarted; -	time_type	mExpires; -	time_type	mStopped; -	time_type	mCount; +	time_type					mHorizon; +	bool						mActive; +	bool						mDone; +	time_type					mStarted; +	time_type					mExpires; +	time_type					mStopped; +	time_type					mCount; + +	const bool					mIncCPU;		// Include CPU metrics in timer +	LLProcInfo::time_type		mUStartCPU; +	LLProcInfo::time_type		mUEndCPU; +	LLProcInfo::time_type		mSStartCPU; +	LLProcInfo::time_type		mSEndCPU;  }; diff --git a/indra/llcommon/llprocinfo.cpp b/indra/llcommon/llprocinfo.cpp new file mode 100644 index 0000000000..c00f979b0b --- /dev/null +++ b/indra/llcommon/llprocinfo.cpp @@ -0,0 +1,94 @@ +/**  +* @file llprocinfo.cpp +* @brief Process, cpu and resource usage information APIs. +* @author monty@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, 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 "llprocinfo.h" + +#if LL_WINDOWS + +#define	PSAPI_VERSION	1 +#include "windows.h" +#include "psapi.h" + +#elif LL_DARWIN + +#include <sys/resource.h> +#include <mach/mach.h> +	 +#else + +#include <sys/time.h> +#include <sys/resource.h> + +#endif // LL_WINDOWS/LL_DARWIN + + +// static +void LLProcInfo::getCPUUsage(time_type & user_time, time_type & system_time) +{ +#if LL_WINDOWS + +	HANDLE self(GetCurrentProcess());			// Does not have to be closed +	FILETIME ft_dummy, ft_system, ft_user; + +	GetProcessTimes(self, &ft_dummy, &ft_dummy, &ft_system, &ft_user); +	ULARGE_INTEGER uli; +	uli.u.LowPart = ft_system.dwLowDateTime; +	uli.u.HighPart = ft_system.dwHighDateTime; +	system_time = uli.QuadPart / U64L(10);		// Convert to uS +	uli.u.LowPart = ft_user.dwLowDateTime; +	uli.u.HighPart = ft_user.dwHighDateTime; +	user_time = uli.QuadPart / U64L(10); +	 +#elif LL_DARWIN + +	struct rusage usage; + +	if (getrusage(RUSAGE_SELF, &usage)) +	{ +		user_time = system_time = time_type(0U); +		return; +	} +	user_time = U64(usage.ru_utime.tv_sec) * U64L(1000000) + usage.ru_utime.tv_usec; +	system_time = U64(usage.ru_stime.tv_sec) * U64L(1000000) + usage.ru_stime.tv_usec; + +#else // Linux + +	struct rusage usage; + +	if (getrusage(RUSAGE_SELF, &usage)) +	{ +		user_time = system_time = time_type(0U); +		return; +	} +	user_time = U64(usage.ru_utime.tv_sec) * U64L(1000000) + usage.ru_utime.tv_usec; +	system_time = U64(usage.ru_stime.tv_sec) * U64L(1000000) + usage.ru_stime.tv_usec; +	 +#endif // LL_WINDOWS/LL_DARWIN/Linux +} + + diff --git a/indra/llcommon/llprocinfo.h b/indra/llcommon/llprocinfo.h new file mode 100644 index 0000000000..e78bcf490a --- /dev/null +++ b/indra/llcommon/llprocinfo.h @@ -0,0 +1,68 @@ +/**  +* @file   llprocinfo.h +* @brief  Interface to process/cpu/resource information services. +* @author monty@lindenlab.com +* +* $LicenseInfo:firstyear=2013&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2013, 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_PROCINFO_H +#define	LL_PROCINFO_H + + +#include "linden_common.h" + +/// @file llprocinfo.h +/// +/// Right now, this is really a namespace disguised as a class. +/// It wraps some types and functions to return information about +/// process resource consumption in a non-OS-specific manner. +/// +/// Threading:  No instances so that's thread-safe.  Implementations +/// of static functions should be thread-safe, they mostly involve +/// direct syscall invocations. +/// +/// Allocation:  Not instantiatable. + +class LL_COMMON_API LLProcInfo +{ +public: +	/// Public types + +	typedef U64 time_type;								/// Relative microseconds +	 +private: +	LLProcInfo();										// Not defined +	~LLProcInfo();										// Not defined +	LLProcInfo(const LLProcInfo &);						// Not defined +	void operator=(const LLProcInfo &);					// Not defined + +public: +	/// Get accumulated system and user CPU time in +	/// microseconds.  Syscalls involved in every invocation. +	/// +	/// Threading:  expected to be safe. +	static void getCPUUsage(time_type & user_time, time_type & system_time); +}; +	 + +#endif	// LL_PROCINFO_H diff --git a/indra/llcommon/tests/lldeadmantimer_test.cpp b/indra/llcommon/tests/lldeadmantimer_test.cpp index 63cab29e04..7fd2dde6e0 100644 --- a/indra/llcommon/tests/lldeadmantimer_test.cpp +++ b/indra/llcommon/tests/lldeadmantimer_test.cpp @@ -28,6 +28,7 @@  #include "../lldeadmantimer.h"  #include "../llsd.h" +#include "../lltimer.h"  #include "../test/lltut.h" @@ -65,14 +66,31 @@ tut::deadmantimer_group_t deadmantimer_instance("LLDeadmanTimer");  template<> template<>  void deadmantimer_object_t::test<1>()  { -	F64 started(42.0), stopped(97.0); -	U64 count(U64L(8)); -	LLDeadmanTimer timer(10.0); - -	ensure_equals("isExpired() returns false after ctor()", timer.isExpired(0, started, stopped, count), false); -	ensure_approximately_equals("t1 - isExpired() does not modify started", started, F64(42.0), 2); -	ensure_approximately_equals("t1 - isExpired() does not modify stopped", stopped, F64(97.0), 2); -	ensure_equals("t1 - isExpired() does not modify count", count, U64L(8)); +	{ +		// Without cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)); +		LLDeadmanTimer timer(10.0, false); + +		ensure_equals("WOCM isExpired() returns false after ctor()", timer.isExpired(0, started, stopped, count), false); +		ensure_approximately_equals("WOCM t1 - isExpired() does not modify started", started, F64(42.0), 2); +		ensure_approximately_equals("WOCM t1 - isExpired() does not modify stopped", stopped, F64(97.0), 2); +		ensure_equals("WOCM t1 - isExpired() does not modify count", count, U64L(8)); +	} + +	{ +		// With cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000); +		LLDeadmanTimer timer(10.0, true); + +		ensure_equals("WCM isExpired() returns false after ctor()", timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), false); +		ensure_approximately_equals("WCM t1 - isExpired() does not modify started", started, F64(42.0), 2); +		ensure_approximately_equals("WCM t1 - isExpired() does not modify stopped", stopped, F64(97.0), 2); +		ensure_equals("WCM t1 - isExpired() does not modify count", count, U64L(8)); +		ensure_equals("WCM t1 - isExpired() does not modify user_cpu", user_cpu, U64L(29000)); +		ensure_equals("WCM t1 - isExpired() does not modify sys_cpu", sys_cpu, U64L(57000)); +	}  } @@ -80,12 +98,25 @@ void deadmantimer_object_t::test<1>()  template<> template<>  void deadmantimer_object_t::test<2>()  { -	F64 started(42.0), stopped(97.0); -	U64 count(U64L(8)); -	LLDeadmanTimer timer(0.0);			// Zero is pre-expired - -	ensure_equals("isExpired() still returns false with 0.0 time ctor()", -				  timer.isExpired(0, started, stopped, count), false); +	{ +		// Without cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)); +		LLDeadmanTimer timer(0.0, false);			// Zero is pre-expired +		 +		ensure_equals("WOCM isExpired() still returns false with 0.0 time ctor()", +					  timer.isExpired(0, started, stopped, count), false); +	} + +	{ +		// With cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000); +		LLDeadmanTimer timer(0.0, true);			// Zero is pre-expired +		 +		ensure_equals("WCM isExpired() still returns false with 0.0 time ctor()", +					  timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), false); +	}  } @@ -94,14 +125,28 @@ void deadmantimer_object_t::test<2>()  template<> template<>  void deadmantimer_object_t::test<3>()  { -	F64 started(42.0), stopped(97.0); -	U64 count(U64L(8)); -	LLDeadmanTimer timer(0.0); - -	timer.start(0); -	ensure_equals("isExpired() returns true with 0.0 horizon time", -				  timer.isExpired(0, started, stopped, count), true); -	ensure_approximately_equals("expired timer with no bell ringing has stopped == started", started, stopped, 8); +	{ +		// Without cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)); +		LLDeadmanTimer timer(0.0, false); + +		timer.start(0); +		ensure_equals("WOCM isExpired() returns true with 0.0 horizon time", +					  timer.isExpired(0, started, stopped, count), true); + 		ensure_approximately_equals("WOCM expired timer with no bell ringing has stopped == started", started, stopped, 8); +	} +	{ +		// With cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000); +		LLDeadmanTimer timer(0.0, true); + +		timer.start(0); +		ensure_equals("WCM isExpired() returns true with 0.0 horizon time", +					  timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), true); +		ensure_approximately_equals("WCM expired timer with no bell ringing has stopped == started", started, stopped, 8); +	}  } @@ -109,15 +154,30 @@ void deadmantimer_object_t::test<3>()  template<> template<>  void deadmantimer_object_t::test<4>()  { -	F64 started(42.0), stopped(97.0); -	U64 count(U64L(8)); -	LLDeadmanTimer timer(0.0); +	{ +		// Without cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)); +		LLDeadmanTimer timer(0.0, false); +	 +		timer.start(0); +		timer.ringBell(LLDeadmanTimer::getNow() + float_time_to_u64(1000.0), 1); +		ensure_equals("WOCM isExpired() returns true with 0.0 horizon time after bell ring", +					  timer.isExpired(0, started, stopped, count), true); +		ensure_approximately_equals("WOCM ringBell has no impact on expired timer leaving stopped == started", started, stopped, 8); +	} +	{ +		// With cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000); +		LLDeadmanTimer timer(0.0, true); -	timer.start(0); -	timer.ringBell(LLDeadmanTimer::getNow() + float_time_to_u64(1000.0), 1); -	ensure_equals("isExpired() returns true with 0.0 horizon time after bell ring", -				  timer.isExpired(0, started, stopped, count), true); -	ensure_approximately_equals("ringBell has no impact on expired timer leaving stopped == started", started, stopped, 8); +		timer.start(0); +		timer.ringBell(LLDeadmanTimer::getNow() + float_time_to_u64(1000.0), 1); +		ensure_equals("WCM isExpired() returns true with 0.0 horizon time after bell ring", +					  timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), true); +		ensure_approximately_equals("WCM ringBell has no impact on expired timer leaving stopped == started", started, stopped, 8); +	}  } @@ -125,16 +185,34 @@ void deadmantimer_object_t::test<4>()  template<> template<>  void deadmantimer_object_t::test<5>()  { -	F64 started(42.0), stopped(97.0); -	U64 count(U64L(8)); -	LLDeadmanTimer timer(10.0); +	{ +		// Without cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)); +		LLDeadmanTimer timer(10.0, false); +	 +		timer.start(0); +		ensure_equals("WOCM isExpired() returns false after starting with 10.0 horizon time", +					  timer.isExpired(0, started, stopped, count), false); +		ensure_approximately_equals("WOCM t5 - isExpired() does not modify started", started, F64(42.0), 2); +		ensure_approximately_equals("WOCM t5 - isExpired() does not modify stopped", stopped, F64(97.0), 2); +		ensure_equals("WOCM t5 - isExpired() does not modify count", count, U64L(8)); +	} +	{ +		// With cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000); +		LLDeadmanTimer timer(10.0, true); -	timer.start(0); -	ensure_equals("isExpired() returns false after starting with 10.0 horizon time", -				  timer.isExpired(0, started, stopped, count), false); -	ensure_approximately_equals("t5 - isExpired() does not modify started", started, F64(42.0), 2); -	ensure_approximately_equals("t5 - isExpired() does not modify stopped", stopped, F64(97.0), 2); -	ensure_equals("t5 - isExpired() does not modify count", count, U64L(8)); +		timer.start(0); +		ensure_equals("WCM isExpired() returns false after starting with 10.0 horizon time", +					  timer.isExpired(0, started, stopped, count, user_cpu, sys_cpu), false); +		ensure_approximately_equals("WCM t5 - isExpired() does not modify started", started, F64(42.0), 2); +		ensure_approximately_equals("WCM t5 - isExpired() does not modify stopped", stopped, F64(97.0), 2); +		ensure_equals("WCM t5 - isExpired() does not modify count", count, U64L(8)); +		ensure_equals("WCM t5 - isExpired() does not modify user_cpu", user_cpu, U64L(29000)); +		ensure_equals("WCM t5 - isExpired() does not modify sys_cpu", sys_cpu, U64L(57000)); +	}  } @@ -142,22 +220,46 @@ void deadmantimer_object_t::test<5>()  template<> template<>  void deadmantimer_object_t::test<6>()  { -	F64 started(42.0), stopped(97.0); -	U64 count(U64L(8)); -	LLDeadmanTimer timer(10.0); - -	// Would like to do subtraction on current time but can't because -	// the implementation on Windows is zero-based.  We wrap around -	// the backside resulting in a large U64 number. +	{ +		// Without cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)); +		LLDeadmanTimer timer(10.0, false); + +		// Would like to do subtraction on current time but can't because +		// the implementation on Windows is zero-based.  We wrap around +		// the backside resulting in a large U64 number. +	 +		LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow()); +		LLDeadmanTimer::time_type now(the_past + float_time_to_u64(5.0)); +		timer.start(the_past); +		ensure_equals("WOCM t6 - isExpired() returns false with 10.0 horizon time starting 5.0 in past", +					  timer.isExpired(now, started, stopped, count), false); +		ensure_approximately_equals("WOCM t6 - isExpired() does not modify started", started, F64(42.0), 2); +		ensure_approximately_equals("WOCM t6 - isExpired() does not modify stopped", stopped, F64(97.0), 2); +		ensure_equals("WOCM t6 - isExpired() does not modify count", count, U64L(8)); +	} +	{ +		// With cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000); +		LLDeadmanTimer timer(10.0, true); + +		// Would like to do subtraction on current time but can't because +		// the implementation on Windows is zero-based.  We wrap around +		// the backside resulting in a large U64 number. -	LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow()); -	LLDeadmanTimer::time_type now(the_past + float_time_to_u64(5.0)); -	timer.start(the_past); -	ensure_equals("isExpired() returns false with 10.0 horizon time starting 5.0 in past", -				  timer.isExpired(now, started, stopped, count), false); -	ensure_approximately_equals("t6 - isExpired() does not modify started", started, F64(42.0), 2); -	ensure_approximately_equals("t6 - isExpired() does not modify stopped", stopped, F64(97.0), 2); -	ensure_equals("t6 - isExpired() does not modify count", count, U64L(8)); +		LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow()); +		LLDeadmanTimer::time_type now(the_past + float_time_to_u64(5.0)); +		timer.start(the_past); +		ensure_equals("WCM t6 - isExpired() returns false with 10.0 horizon time starting 5.0 in past", +					  timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false); +		ensure_approximately_equals("WCM t6 - isExpired() does not modify started", started, F64(42.0), 2); +		ensure_approximately_equals("WCM t6 - isExpired() does not modify stopped", stopped, F64(97.0), 2); +		ensure_equals("t6 - isExpired() does not modify count", count, U64L(8)); +		ensure_equals("WCM t6 - isExpired() does not modify user_cpu", user_cpu, U64L(29000)); +		ensure_equals("WCM t6 - isExpired() does not modify sys_cpu", sys_cpu, U64L(57000)); +	}  } @@ -165,20 +267,40 @@ void deadmantimer_object_t::test<6>()  template<> template<>  void deadmantimer_object_t::test<7>()  { -	F64 started(42.0), stopped(97.0); -	U64 count(U64L(8)); -	LLDeadmanTimer timer(10.0); - -	// Would like to do subtraction on current time but can't because -	// the implementation on Windows is zero-based.  We wrap around -	// the backside resulting in a large U64 number. +	{ +		// Without cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)); +		LLDeadmanTimer timer(10.0, false); +		 +		// Would like to do subtraction on current time but can't because +		// the implementation on Windows is zero-based.  We wrap around +		// the backside resulting in a large U64 number. +	 +		LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow()); +		LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0)); +		timer.start(the_past); +		ensure_equals("WOCM t7 - isExpired() returns true with 10.0 horizon time starting 20.0 in past", +					  timer.isExpired(now,started, stopped, count), true); +		ensure_approximately_equals("WOCM t7 - starting before horizon still gives equal started / stopped", started, stopped, 8); +	} +	{ +		// With cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000); +		LLDeadmanTimer timer(10.0, true); +		 +		// Would like to do subtraction on current time but can't because +		// the implementation on Windows is zero-based.  We wrap around +		// the backside resulting in a large U64 number. -	LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow()); -	LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0)); -	timer.start(the_past); -	ensure_equals("isExpired() returns true with 10.0 horizon time starting 20.0 in past", -				  timer.isExpired(now,started, stopped, count), true); -	ensure_approximately_equals("starting before horizon still gives equal started / stopped", started, stopped, 8); +		LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow()); +		LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0)); +		timer.start(the_past); +		ensure_equals("WCM t7 - isExpired() returns true with 10.0 horizon time starting 20.0 in past", +					  timer.isExpired(now,started, stopped, count, user_cpu, sys_cpu), true); +		ensure_approximately_equals("WOCM t7 - starting before horizon still gives equal started / stopped", started, stopped, 8); +	}  } @@ -186,28 +308,60 @@ void deadmantimer_object_t::test<7>()  template<> template<>  void deadmantimer_object_t::test<8>()  { -	F64 started(42.0), stopped(97.0); -	U64 count(U64L(8)); -	LLDeadmanTimer timer(10.0); - -	// Would like to do subtraction on current time but can't because -	// the implementation on Windows is zero-based.  We wrap around -	// the backside resulting in a large U64 number. +	{ +		// Without cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)); +		LLDeadmanTimer timer(10.0, false); + +		// Would like to do subtraction on current time but can't because +		// the implementation on Windows is zero-based.  We wrap around +		// the backside resulting in a large U64 number. -	LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow()); -	LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0)); -	timer.start(the_past); -	ensure_equals("t8 - isExpired() returns true with 10.0 horizon time starting 20.0 in past", -				  timer.isExpired(now, started, stopped, count), true); - -	started = 42.0; -	stopped = 97.0; -	count = U64L(8); -	ensure_equals("t8 - second isExpired() returns false after true", -				  timer.isExpired(now, started, stopped, count), false); -	ensure_approximately_equals("t8 - 2nd isExpired() does not modify started", started, F64(42.0), 2); -	ensure_approximately_equals("t8 - 2nd isExpired() does not modify stopped", stopped, F64(97.0), 2); -	ensure_equals("t8 - 2nd isExpired() does not modify count", count, U64L(8)); +		LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow()); +		LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0)); +		timer.start(the_past); +		ensure_equals("WOCM t8 - isExpired() returns true with 10.0 horizon time starting 20.0 in past", +					  timer.isExpired(now, started, stopped, count), true); +		 +		started = 42.0; +		stopped = 97.0; +		count = U64L(8); +		ensure_equals("WOCM t8 - second isExpired() returns false after true", +					  timer.isExpired(now, started, stopped, count), false); +		ensure_approximately_equals("WOCM t8 - 2nd isExpired() does not modify started", started, F64(42.0), 2); +		ensure_approximately_equals("WOCM t8 - 2nd isExpired() does not modify stopped", stopped, F64(97.0), 2); +		ensure_equals("WOCM t8 - 2nd isExpired() does not modify count", count, U64L(8)); +	} +	{ +		// With cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000); +		LLDeadmanTimer timer(10.0, true); + +		// Would like to do subtraction on current time but can't because +		// the implementation on Windows is zero-based.  We wrap around +		// the backside resulting in a large U64 number. +	 +		LLDeadmanTimer::time_type the_past(LLDeadmanTimer::getNow()); +		LLDeadmanTimer::time_type now(the_past + float_time_to_u64(20.0)); +		timer.start(the_past); +		ensure_equals("WCM t8 - isExpired() returns true with 10.0 horizon time starting 20.0 in past", +					  timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true); +		 +		started = 42.0; +		stopped = 97.0; +		count = U64L(8); +		user_cpu = 29000; +		sys_cpu = 57000; +		ensure_equals("WCM t8 - second isExpired() returns false after true", +					  timer.isExpired(now, started, stopped, count), false); +		ensure_approximately_equals("WCM t8 - 2nd isExpired() does not modify started", started, F64(42.0), 2); +		ensure_approximately_equals("WCM t8 - 2nd isExpired() does not modify stopped", stopped, F64(97.0), 2); +		ensure_equals("WCM t8 - 2nd isExpired() does not modify count", count, U64L(8)); +		ensure_equals("WCM t8 - 2nd isExpired() does not modify user_cpu", user_cpu, U64L(29000)); +		ensure_equals("WCM t8 - 2nd isExpired() does not modify sys_cpu", sys_cpu, U64L(57000)); +	}  } @@ -215,46 +369,92 @@ void deadmantimer_object_t::test<8>()  template<> template<>  void deadmantimer_object_t::test<9>()  { -	F64 started(42.0), stopped(97.0); -	U64 count(U64L(8)); -	LLDeadmanTimer timer(5.0); - -	LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow()); -	F64 real_start(u64_time_to_float(now)); -	timer.start(0); - -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	ensure_equals("t9 - 5.0 horizon timer has not timed out after 10 1-second bell rings", -				  timer.isExpired(now, started, stopped, count), false); -	F64 last_good_ring(u64_time_to_float(now)); - -	// Jump forward and expire -	now += float_time_to_u64(10.0); -	ensure_equals("t9 - 5.0 horizon timer expires on 10-second jump", -				  timer.isExpired(now, started, stopped, count), true); -	ensure_approximately_equals("t9 - started matches start() time", started, real_start, 4); -	ensure_approximately_equals("t9 - stopped matches last ringBell() time", stopped, last_good_ring, 4); -	ensure_equals("t9 - 10 good ringBell()s", count, U64L(10)); -	ensure_equals("t9 - single read only", timer.isExpired(now, started, stopped, count), false); +	{ +		// Without cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)); +		LLDeadmanTimer timer(5.0, false); + +		LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow()); +		F64 real_start(u64_time_to_float(now)); +		timer.start(0); + +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		ensure_equals("WOCM t9 - 5.0 horizon timer has not timed out after 10 1-second bell rings", +					  timer.isExpired(now, started, stopped, count), false); +		F64 last_good_ring(u64_time_to_float(now)); + +		// Jump forward and expire +		now += float_time_to_u64(10.0); +		ensure_equals("WOCM t9 - 5.0 horizon timer expires on 10-second jump", +					  timer.isExpired(now, started, stopped, count), true); +		ensure_approximately_equals("WOCM t9 - started matches start() time", started, real_start, 4); +		ensure_approximately_equals("WOCM t9 - stopped matches last ringBell() time", stopped, last_good_ring, 4); +		ensure_equals("WOCM t9 - 10 good ringBell()s", count, U64L(10)); +		ensure_equals("WOCM t9 - single read only", timer.isExpired(now, started, stopped, count), false); +	} +	{ +		// With cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000); +		LLDeadmanTimer timer(5.0, true); + +		LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow()); +		F64 real_start(u64_time_to_float(now)); +		timer.start(0); + +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		ensure_equals("WCM t9 - 5.0 horizon timer has not timed out after 10 1-second bell rings", +					  timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false); +		F64 last_good_ring(u64_time_to_float(now)); + +		// Jump forward and expire +		now += float_time_to_u64(10.0); +		ensure_equals("WCM t9 - 5.0 horizon timer expires on 10-second jump", +					  timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true); +		ensure_approximately_equals("WCM t9 - started matches start() time", started, real_start, 4); +		ensure_approximately_equals("WCM t9 - stopped matches last ringBell() time", stopped, last_good_ring, 4); +		ensure_equals("WCM t9 - 10 good ringBell()s", count, U64L(10)); +		ensure_equals("WCM t9 - single read only", timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false); +	}  } @@ -262,83 +462,167 @@ void deadmantimer_object_t::test<9>()  template<> template<>  void deadmantimer_object_t::test<10>()  { -	F64 started(42.0), stopped(97.0); -	U64 count(U64L(8)); -	LLDeadmanTimer timer(5.0); - -	LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow()); -	F64 real_start(u64_time_to_float(now)); -	timer.start(0); - -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	ensure_equals("t10 - 5.0 horizon timer has not timed out after 10 1-second bell rings", -				  timer.isExpired(now, started, stopped, count), false); -	F64 last_good_ring(u64_time_to_float(now)); - -	// Jump forward and expire -	now += float_time_to_u64(10.0); -	ensure_equals("t10 - 5.0 horizon timer expires on 10-second jump", -				  timer.isExpired(now, started, stopped, count), true); -	ensure_approximately_equals("t10 - started matches start() time", started, real_start, 4); -	ensure_approximately_equals("t10 - stopped matches last ringBell() time", stopped, last_good_ring, 4); -	ensure_equals("t10 - 10 good ringBell()s", count, U64L(10)); -	ensure_equals("t10 - single read only", timer.isExpired(now, started, stopped, count), false); - -	// Jump forward and restart -	now += float_time_to_u64(1.0); -	real_start = u64_time_to_float(now); -	timer.start(now); - -	// Run a modified bell ring sequence -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	now += float_time_to_u64(1.0); -	timer.ringBell(now, 1); -	ensure_equals("t10 - 5.0 horizon timer has not timed out after 8 1-second bell rings", -				  timer.isExpired(now, started, stopped, count), false); -	last_good_ring = u64_time_to_float(now); - -	// Jump forward and expire -	now += float_time_to_u64(10.0); -	ensure_equals("t10 - 5.0 horizon timer expires on 8-second jump", -				  timer.isExpired(now, started, stopped, count), true); -	ensure_approximately_equals("t10 - 2nd started matches start() time", started, real_start, 4); -	ensure_approximately_equals("t10 - 2nd stopped matches last ringBell() time", stopped, last_good_ring, 4); -	ensure_equals("t10 - 8 good ringBell()s", count, U64L(8)); -	ensure_equals("t10 - single read only - 2nd start", -				  timer.isExpired(now, started, stopped, count), false); +	{ +		// Without cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)); +		LLDeadmanTimer timer(5.0, false); + +		LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow()); +		F64 real_start(u64_time_to_float(now)); +		timer.start(0); + +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		ensure_equals("WOCM t10 - 5.0 horizon timer has not timed out after 10 1-second bell rings", +					  timer.isExpired(now, started, stopped, count), false); +		F64 last_good_ring(u64_time_to_float(now)); + +		// Jump forward and expire +		now += float_time_to_u64(10.0); +		ensure_equals("WOCM t10 - 5.0 horizon timer expires on 10-second jump", +					  timer.isExpired(now, started, stopped, count), true); +		ensure_approximately_equals("WOCM t10 - started matches start() time", started, real_start, 4); +		ensure_approximately_equals("WOCM t10 - stopped matches last ringBell() time", stopped, last_good_ring, 4); +		ensure_equals("WOCM t10 - 10 good ringBell()s", count, U64L(10)); +		ensure_equals("WOCM t10 - single read only", timer.isExpired(now, started, stopped, count), false); +		 +		// Jump forward and restart +		now += float_time_to_u64(1.0); +		real_start = u64_time_to_float(now); +		timer.start(now); +		 +		// Run a modified bell ring sequence +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		ensure_equals("WOCM t10 - 5.0 horizon timer has not timed out after 8 1-second bell rings", +					  timer.isExpired(now, started, stopped, count), false); +		last_good_ring = u64_time_to_float(now); + +		// Jump forward and expire +		now += float_time_to_u64(10.0); +		ensure_equals("WOCM t10 - 5.0 horizon timer expires on 8-second jump", +					  timer.isExpired(now, started, stopped, count), true); +		ensure_approximately_equals("WOCM t10 - 2nd started matches start() time", started, real_start, 4); +		ensure_approximately_equals("WOCM t10 - 2nd stopped matches last ringBell() time", stopped, last_good_ring, 4); +		ensure_equals("WOCM t10 - 8 good ringBell()s", count, U64L(8)); +		ensure_equals("WOCM t10 - single read only - 2nd start", +					  timer.isExpired(now, started, stopped, count), false); +	} +	{ +		// With cpu metrics +		F64 started(42.0), stopped(97.0); +		U64 count(U64L(8)), user_cpu(29000), sys_cpu(57000); + +		LLDeadmanTimer timer(5.0, true); + +		LLDeadmanTimer::time_type now(LLDeadmanTimer::getNow()); +		F64 real_start(u64_time_to_float(now)); +		timer.start(0); + +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		ensure_equals("WCM t10 - 5.0 horizon timer has not timed out after 10 1-second bell rings", +					  timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false); +		F64 last_good_ring(u64_time_to_float(now)); + +		// Jump forward and expire +		now += float_time_to_u64(10.0); +		ensure_equals("WCM t10 - 5.0 horizon timer expires on 10-second jump", +					  timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true); +		ensure_approximately_equals("WCM t10 - started matches start() time", started, real_start, 4); +		ensure_approximately_equals("WCM t10 - stopped matches last ringBell() time", stopped, last_good_ring, 4); +		ensure_equals("WCM t10 - 10 good ringBell()s", count, U64L(10)); +		ensure_equals("WCM t10 - single read only", timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false); +		 +		// Jump forward and restart +		now += float_time_to_u64(1.0); +		real_start = u64_time_to_float(now); +		timer.start(now); +		 +		// Run a modified bell ring sequence +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		now += float_time_to_u64(1.0); +		timer.ringBell(now, 1); +		ensure_equals("WCM t10 - 5.0 horizon timer has not timed out after 8 1-second bell rings", +					  timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false); +		last_good_ring = u64_time_to_float(now); + +		// Jump forward and expire +		now += float_time_to_u64(10.0); +		ensure_equals("WCM t10 - 5.0 horizon timer expires on 8-second jump", +					  timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), true); +		ensure_approximately_equals("WCM t10 - 2nd started matches start() time", started, real_start, 4); +		ensure_approximately_equals("WCM t10 - 2nd stopped matches last ringBell() time", stopped, last_good_ring, 4); +		ensure_equals("WCM t10 - 8 good ringBell()s", count, U64L(8)); +		ensure_equals("WCM t10 - single read only - 2nd start", +					  timer.isExpired(now, started, stopped, count, user_cpu, sys_cpu), false); +	}  } +  } // end namespace tut diff --git a/indra/llcommon/tests/llprocinfo_test.cpp b/indra/llcommon/tests/llprocinfo_test.cpp new file mode 100644 index 0000000000..12d5a695ee --- /dev/null +++ b/indra/llcommon/tests/llprocinfo_test.cpp @@ -0,0 +1,91 @@ +/**  + * @file llprocinfo_test.cpp + * @brief Tests for the LLProcInfo class. + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "../llprocinfo.h" + +#include "../test/lltut.h" +#include "../lltimer.h" + + +static const LLProcInfo::time_type bad_user(289375U), bad_system(275U); + + +namespace tut +{ + +struct procinfo_test +{ +	procinfo_test() +		{ +		} +}; + +typedef test_group<procinfo_test> procinfo_group_t; +typedef procinfo_group_t::object procinfo_object_t; +tut::procinfo_group_t procinfo_instance("LLProcInfo"); + + +// Basic invocation works +template<> template<> +void procinfo_object_t::test<1>() +{ +	LLProcInfo::time_type user(bad_user), system(bad_system); + +	set_test_name("getCPUUsage() basic function"); + +	LLProcInfo::getCPUUsage(user, system); +	 +	ensure_not_equals("getCPUUsage() writes to its user argument", user, bad_user); +	ensure_not_equals("getCPUUsage() writes to its system argument", system, bad_system); +} + + +// Time increases +template<> template<> +void procinfo_object_t::test<2>() +{ +	LLProcInfo::time_type user(bad_user), system(bad_system); +	LLProcInfo::time_type user2(bad_user), system2(bad_system); + +	set_test_name("getCPUUsage() increases over time"); + +	LLProcInfo::getCPUUsage(user, system); +	 +	for (int i(0); i < 100000; ++i) +	{ +		ms_sleep(0); +	} +	 +	LLProcInfo::getCPUUsage(user2, system2); + +	ensure_equals("getCPUUsage() user value doesn't decrease over time", user2 >= user, true); +	ensure_equals("getCPUUsage() system value doesn't decrease over time", system2 >= system, true); +} + + +} // end namespace tut diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp index 4386e3283b..142344e277 100755 --- a/indra/newview/llappcorehttp.cpp +++ b/indra/newview/llappcorehttp.cpp @@ -139,7 +139,8 @@ void LLAppCoreHttp::init()  		static const std::string mesh_concur("MeshMaxConcurrentRequests");  		if (gSavedSettings.controlExists(mesh_concur))  		{ -			U32 setting(llmin(gSavedSettings.getU32(mesh_concur), U32(32))); +			U32 setting(llmin(gSavedSettings.getU32(mesh_concur), 256U) / 4U); +			setting = llmax(setting, 2U);  			if (setting > 0)  			{ diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index b52c86dd4e..8f6860aec7 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -98,7 +98,7 @@ U32 LLMeshRepository::sLODPending = 0;  U32 LLMeshRepository::sCacheBytesRead = 0;  U32 LLMeshRepository::sCacheBytesWritten = 0;  U32 LLMeshRepository::sPeakKbps = 0; -LLDeadmanTimer LLMeshRepository::sQuiescentTimer(15.0); +LLDeadmanTimer LLMeshRepository::sQuiescentTimer(15.0, true);	// true -> gather cpu metrics  const U32 MAX_TEXTURE_UPLOAD_RETRIES = 5; @@ -218,7 +218,8 @@ public:  	LLMeshHandlerBase()  		: LLCore::HttpHandler(),  		  mMeshParams(), -		  mProcessed(false) +		  mProcessed(false), +		  mHttpHandle(LLCORE_HTTP_HANDLE_INVALID)  	{}  	virtual ~LLMeshHandlerBase(); @@ -365,154 +366,6 @@ public:  	U32			mOffset;  }; -	 -class LLMeshHeaderResponder : public LLCurl::Responder -{ -public: -	LLVolumeParams mMeshParams; -	bool mProcessed; - -	LLMeshHeaderResponder(const LLVolumeParams& mesh_params) -		: mMeshParams(mesh_params) -	{ -		LLMeshRepoThread::incActiveHeaderRequests(); -		mProcessed = false; -	} - -	~LLMeshHeaderResponder() -	{ -		if (!LLApp::isQuitting()) -		{ -			if (!mProcessed) -			{ //something went wrong, retry -				llwarns << "Timeout or service unavailable, retrying." << llendl; -				LLMeshRepository::sHTTPRetryCount++; -				LLMeshRepoThread::HeaderRequest req(mMeshParams); -				LLMutexLock lock(gMeshRepo.mThread->mMutex); -				gMeshRepo.mThread->mHeaderReqQ.push(req); -			} - -			LLMeshRepoThread::decActiveHeaderRequests(); -		} -	} - -	virtual void completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer); - -}; - -class LLMeshLODResponder : public LLCurl::Responder -{ -public: -	LLVolumeParams mMeshParams; -	S32 mLOD; -	U32 mRequestedBytes; -	U32 mOffset; -	bool mProcessed; - -	LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes) -		: mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes) -	{ -		LLMeshRepoThread::incActiveLODRequests(); -		mProcessed = false; -	} - -	~LLMeshLODResponder() -	{ -		if (!LLApp::isQuitting()) -		{ -			if (!mProcessed) -			{ -				llwarns << "Killed without being processed, retrying." << llendl; -				LLMeshRepository::sHTTPRetryCount++; -				gMeshRepo.mThread->lockAndLoadMeshLOD(mMeshParams, mLOD); -			} -			LLMeshRepoThread::decActiveLODRequests(); -		} -	} - -	virtual void completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer); - -}; - -class LLMeshSkinInfoResponder : public LLCurl::Responder -{ -public: -	LLUUID mMeshID; -	U32 mRequestedBytes; -	U32 mOffset; -	bool mProcessed; - -	LLMeshSkinInfoResponder(const LLUUID& id, U32 offset, U32 size) -		: mMeshID(id), mRequestedBytes(size), mOffset(offset) -	{ -		mProcessed = false; -	} - -	~LLMeshSkinInfoResponder() -	{ -		llassert(mProcessed); -	} - -	virtual void completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer); - -}; - -class LLMeshDecompositionResponder : public LLCurl::Responder -{ -public: -	LLUUID mMeshID; -	U32 mRequestedBytes; -	U32 mOffset; -	bool mProcessed; - -	LLMeshDecompositionResponder(const LLUUID& id, U32 offset, U32 size) -		: mMeshID(id), mRequestedBytes(size), mOffset(offset) -	{ -		mProcessed = false; -	} - -	~LLMeshDecompositionResponder() -	{ -		llassert(mProcessed); -	} - -	virtual void completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer); - -}; - -class LLMeshPhysicsShapeResponder : public LLCurl::Responder -{ -public: -	LLUUID mMeshID; -	U32 mRequestedBytes; -	U32 mOffset; -	bool mProcessed; - -	LLMeshPhysicsShapeResponder(const LLUUID& id, U32 offset, U32 size) -		: mMeshID(id), mRequestedBytes(size), mOffset(offset) -	{ -		mProcessed = false; -	} - -	~LLMeshPhysicsShapeResponder() -	{ -		llassert(mProcessed); -	} - -	virtual void completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer); - -}; -  void log_upload_error(S32 status, const LLSD& content, std::string stage, std::string model_name)  {  	// Add notification popup. @@ -753,20 +606,24 @@ void LLMeshRepoThread::run()  	while (!LLApp::isQuitting())  	{ +		if (! mHttpRequestSet.empty()) +		{ +			mHttpRequest->update(0L); +		} +  		mWaiting = true;  		mSignal->wait();  		mWaiting = false; - -		if (! LLApp::isQuitting() && ! mHttpRequestSet.empty()) +		 +		if (! LLApp::isQuitting())  		{  			static U32 count = 0; -  			static F32 last_hundred = gFrameTimeSeconds;  			if (gFrameTimeSeconds - last_hundred > 1.f)  			{ //a second has gone by, clear count  				last_hundred = gFrameTimeSeconds; -				count = 0;	 +				count = 0;  			}  			// NOTE: throttling intentionally favors LOD requests over header requests @@ -846,7 +703,6 @@ void LLMeshRepoThread::run()  			}  			mCurlRequest->process(); -			mHttpRequest->update(0L);  		}  	} @@ -1002,16 +858,30 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  			}  			//reading from VFS failed for whatever reason, fetch from sim -			std::vector<std::string> headers; -			headers.push_back("Accept: application/octet-stream"); -  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{				 -				ret = mCurlRequest->getByteRange(http_url, headers, offset, size, -												 new LLMeshSkinInfoResponder(mesh_id, offset, size)); -				if(ret) +			{ +				LLMeshSkinInfoHandler * handler = new LLMeshSkinInfoHandler(mesh_id, offset, size); +				// LL_WARNS("Mesh") << "MESH:  Issuing Skin Info Request" << LL_ENDL; +				LLCore::HttpHandle handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass, +																			  0,				// *TODO:  Get better priority value +																			  http_url, +																			  offset, +																			  size, +																			  mHttpOptions, +																			  mHttpHeaders, +																			  handler); +				if (LLCORE_HTTP_HANDLE_INVALID == handle) +				{ +					// *TODO:  Better error message +					llwarns << "HTTP GET request failed for mesh " << mID << llendl; +					delete handler; +					ret = false; +				} +				else  				{ +					handler->mHttpHandle = handle; +					mHttpRequestSet.insert(handler);  					LLMeshRepository::sHTTPRequestCount++;  				}  			} @@ -1084,16 +954,30 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  			}  			//reading from VFS failed for whatever reason, fetch from sim -			std::vector<std::string> headers; -			headers.push_back("Accept: application/octet-stream"); -  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{				 -				ret = mCurlRequest->getByteRange(http_url, headers, offset, size, -												 new LLMeshDecompositionResponder(mesh_id, offset, size)); -				if(ret) +			{ +				LLMeshDecompositionHandler * handler = new LLMeshDecompositionHandler(mesh_id, offset, size); +				// LL_WARNS("Mesh") << "MESH:  Issuing Decomp Request" << LL_ENDL; +				LLCore::HttpHandle handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass, +																			  0,	// *TODO:  Get better priority value +																			  http_url, +																			  offset, +																			  size, +																			  mHttpOptions, +																			  mHttpHeaders, +																			  handler); +				if (LLCORE_HTTP_HANDLE_INVALID == handle)  				{ +					// *TODO:  Better error message +					llwarns << "HTTP GET request failed for decomposition mesh " << mID << llendl; +					delete handler; +					ret = false; +				} +				else +				{ +					handler->mHttpHandle = handle; +					mHttpRequestSet.insert(handler);  					LLMeshRepository::sHTTPRequestCount++;  				}  			} @@ -1165,17 +1049,30 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  			}  			//reading from VFS failed for whatever reason, fetch from sim -			std::vector<std::string> headers; -			headers.push_back("Accept: application/octet-stream"); -  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{				 -				ret = mCurlRequest->getByteRange(http_url, headers, offset, size, -												 new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); - -				if(ret) +			{ +				LLMeshPhysicsShapeHandler * handler = new LLMeshPhysicsShapeHandler(mesh_id, offset, size); +				// LL_WARNS("Mesh") << "MESH:  Issuing Physics Shape Request" << LL_ENDL; +				LLCore::HttpHandle handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass, +																			  0,		// *TODO:  Get better priority value +																			  http_url, +																			  offset, +																			  size, +																			  mHttpOptions, +																			  mHttpHeaders, +																			  handler); +				if (LLCORE_HTTP_HANDLE_INVALID == handle) +				{ +					// *TODO:  Better error message +					llwarns << "HTTP GET request failed for physics shape mesh " << mID << llendl; +					delete handler; +					ret = false; +				} +				else  				{ +					handler->mHttpHandle = handle; +					mHttpRequestSet.insert(handler);  					LLMeshRepository::sHTTPRequestCount++;  				}  			} @@ -1248,19 +1145,15 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c  	//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())  	{  		//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		 -#if 0 -		retval = mCurlRequest->getByteRange(http_url, headers, 0, MESH_HEADER_SIZE, new LLMeshHeaderResponder(mesh_params)); -#else +  		LLMeshHeaderHandler * handler = new LLMeshHeaderHandler(mesh_params); +		// LL_WARNS("Mesh") << "MESH:  Issuing Request" << LL_ENDL;  		LLCore::HttpHandle handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass,  																	  0,				// *TODO:  Get better priority value  																	  http_url, @@ -1280,10 +1173,6 @@ bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params, U32& c  		{  			handler->mHttpHandle = handle;  			mHttpRequestSet.insert(handler); -		} -#endif		 -		if(retval) -		{  			LLMeshRepository::sHTTPRequestCount++;  		}  		count++; @@ -1347,17 +1236,30 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,  			}  			//reading from VFS failed for whatever reason, fetch from sim -			std::vector<std::string> headers; -			headers.push_back("Accept: application/octet-stream"); -  			std::string http_url = constructUrl(mesh_id);  			if (!http_url.empty()) -			{				 -				retval = mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, -										   new LLMeshLODResponder(mesh_params, lod, offset, size)); - -				if(retval) +			{ +				LLMeshLODHandler * handler = new LLMeshLODHandler(mesh_params, lod, offset, size); +				// LL_WARNS("Mesh") << "MESH:  Issuing LOD Request" << LL_ENDL; +				LLCore::HttpHandle handle = mHttpRequest->requestGetByteRange(mHttpPolicyClass, +																			  0,		// *TODO:  Get better priority value +																			  http_url, +																			  offset, +																			  size, +																			  mHttpOptions, +																			  mHttpHeaders, +																			  handler); +				if (LLCORE_HTTP_HANDLE_INVALID == handle)  				{ +					// *TODO:  Better error message +					llwarns << "HTTP GET request failed for LOD mesh " << mID << llendl; +					delete handler; +					retval = false; +				} +				else +				{ +					handler->mHttpHandle = handle; +					mHttpRequestSet.insert(handler);  					LLMeshRepository::sHTTPRequestCount++;  				}  				count++; @@ -2120,270 +2022,12 @@ void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header)  } -void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer) -{ -	mProcessed = true; -	 -	// thread could have already be destroyed during logout -	if( !gMeshRepo.mThread ) -	{ -		return; -	} -	 -	S32 data_size = buffer->countAfter(channels.in(), NULL); - -	if (status < 200 || status > 400) -	{ -		llwarns << status << ": " << reason << llendl; -	} - -	if (data_size < mRequestedBytes) -	{ -		if (status == 499 || status == 503) -		{ //timeout or service unavailable, try again -			llwarns << "Timeout or service unavailable, retrying." << llendl; -			LLMeshRepository::sHTTPRetryCount++; -			gMeshRepo.mThread->loadMeshLOD(mMeshParams, mLOD); -		} -		else -		{ -			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint -			llwarns << "Unhandled status " << status << llendl; -		} -		return; -	} - -	LLMeshRepository::sBytesReceived += mRequestedBytes; - -	U8* data = NULL; - -	if (data_size > 0) -	{ -		data = new U8[data_size]; -		buffer->readAfter(channels.in(), NULL, data, data_size); -	} - -	if (gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size)) -	{ -		//good fetch from sim, write to VFS for caching -		LLVFile file(gVFS, mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLVFile::WRITE); - -		S32 offset = mOffset; -		S32 size = mRequestedBytes; - -		if (file.getSize() >= offset+size) -		{ -			file.seek(offset); -			file.write(data, size); -			LLMeshRepository::sCacheBytesWritten += size; -		} -	} - -	delete [] data; -} - -void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer) -{ -	mProcessed = true; - -	// thread could have already be destroyed during logout -	if( !gMeshRepo.mThread ) -	{ -		return; -	} - -	S32 data_size = buffer->countAfter(channels.in(), NULL); - -	if (status < 200 || status > 400) -	{ -		llwarns << status << ": " << reason << llendl; -	} - -	if (data_size < mRequestedBytes) -	{ -		if (status == 499 || status == 503) -		{ //timeout or service unavailable, try again -			llwarns << "Timeout or service unavailable, retrying." << llendl; -			LLMeshRepository::sHTTPRetryCount++; -			gMeshRepo.mThread->loadMeshSkinInfo(mMeshID); -		} -		else -		{ -			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint -			llwarns << "Unhandled status " << status << llendl; -		} -		return; -	} - -	LLMeshRepository::sBytesReceived += mRequestedBytes; - -	U8* data = NULL; - -	if (data_size > 0) -	{ -		data = new U8[data_size]; -		buffer->readAfter(channels.in(), NULL, data, data_size); -	} - -	if (gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size)) -	{ -		//good fetch from sim, write to VFS for caching -		LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); - -		S32 offset = mOffset; -		S32 size = mRequestedBytes; - -		if (file.getSize() >= offset+size) -		{ -			LLMeshRepository::sCacheBytesWritten += size; -			file.seek(offset); -			file.write(data, size); -		} -	} - -	delete [] data; -} - -void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer) -{ -	mProcessed = true; -	 -	if( !gMeshRepo.mThread ) -	{ -		return; -	} - -	S32 data_size = buffer->countAfter(channels.in(), NULL); - -	if (status < 200 || status > 400) -	{ -		llwarns << status << ": " << reason << llendl; -	} - -	if (data_size < mRequestedBytes) -	{ -		if (status == 499 || status == 503) -		{ //timeout or service unavailable, try again -			llwarns << "Timeout or service unavailable, retrying." << llendl; -			LLMeshRepository::sHTTPRetryCount++; -			gMeshRepo.mThread->loadMeshDecomposition(mMeshID); -		} -		else -		{ -			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint -			llwarns << "Unhandled status " << status << llendl; -		} -		return; -	} - -	LLMeshRepository::sBytesReceived += mRequestedBytes; - -	U8* data = NULL; - -	if (data_size > 0) -	{ -		data = new U8[data_size]; -		buffer->readAfter(channels.in(), NULL, data, data_size); -	} - -	if (gMeshRepo.mThread->decompositionReceived(mMeshID, data, data_size)) -	{ -		//good fetch from sim, write to VFS for caching -		LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); - -		S32 offset = mOffset; -		S32 size = mRequestedBytes; - -		if (file.getSize() >= offset+size) -		{ -			LLMeshRepository::sCacheBytesWritten += size; -			file.seek(offset); -			file.write(data, size); -		} -	} - -	delete [] data; -} - -void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer) -{ -	mProcessed = true; - -	// thread could have already be destroyed during logout -	if( !gMeshRepo.mThread ) -	{ -		return; -	} - -	S32 data_size = buffer->countAfter(channels.in(), NULL); - -	if (status < 200 || status > 400) -	{ -		llwarns << status << ": " << reason << llendl; -	} - -	if (data_size < mRequestedBytes) -	{ -		if (status == 499 || status == 503) -		{ //timeout or service unavailable, try again -			llwarns << "Timeout or service unavailable, retrying." << llendl; -			LLMeshRepository::sHTTPRetryCount++; -			gMeshRepo.mThread->loadMeshPhysicsShape(mMeshID); -		} -		else -		{ -			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint -			llwarns << "Unhandled status " << status << llendl; -		} -		return; -	} - -	LLMeshRepository::sBytesReceived += mRequestedBytes; - -	U8* data = NULL; - -	if (data_size > 0) -	{ -		data = new U8[data_size]; -		buffer->readAfter(channels.in(), NULL, data, data_size); -	} - -	if (gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size)) -	{ -		//good fetch from sim, write to VFS for caching -		LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); - -		S32 offset = mOffset; -		S32 size = mRequestedBytes; - -		if (file.getSize() >= offset+size) -		{ -			LLMeshRepository::sCacheBytesWritten += size; -			file.seek(offset); -			file.write(data, size); -		} -	} - -	delete [] data; -} - -	  LLMeshHandlerBase::~LLMeshHandlerBase()  {} -  void LLMeshHandlerBase::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)  {  	mProcessed = true; -  	LLCore::HttpStatus status(response->getStatus());  	if (! status)  	{ @@ -2442,9 +2086,9 @@ LLMeshHeaderHandler::~LLMeshHeaderHandler()  	}  } -  void LLMeshHeaderHandler::processFailure(LLCore::HttpStatus status)  { +	LL_WARNS("Mesh") << "MESH:  Processing Failure" << LL_ENDL;  	if (is_retryable(status))  	{  		llwarns << "Timeout or service unavailable, retrying." << llendl; @@ -2460,9 +2104,9 @@ void LLMeshHeaderHandler::processFailure(LLCore::HttpStatus status)  	}  } -  void LLMeshHeaderHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size)  { +	// LL_WARNS("Mesh") << "MESH:  Processing Data" << LL_ENDL;  	bool success = gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size);  	llassert(success);  	if (! success) @@ -2530,7 +2174,6 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * body, U8 * data, S32  	}  } -  LLMeshLODHandler::~LLMeshLODHandler()  {  	if (! LLApp::isQuitting()) @@ -2580,7 +2223,6 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * body, U8 * data, S32 da  	}  } -  LLMeshSkinInfoHandler::~LLMeshSkinInfoHandler()  {  		llassert(mProcessed); @@ -2621,7 +2263,6 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * body, U8 * data, S  	}  } -  LLMeshDecompositionHandler::~LLMeshDecompositionHandler()  {  		llassert(mProcessed); @@ -2662,7 +2303,6 @@ void LLMeshDecompositionHandler::processData(LLCore::BufferArray * body, U8 * da  	}  } -  LLMeshPhysicsShapeHandler::~LLMeshPhysicsShapeHandler()  {  		llassert(mProcessed); @@ -2684,7 +2324,6 @@ void LLMeshPhysicsShapeHandler::processFailure(LLCore::HttpStatus status)  	}  } -	  void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size)  {  	if (gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size)) @@ -2704,134 +2343,6 @@ void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * body, U8 * dat  	}  } - -void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, -							  const LLChannelDescriptors& channels, -							  const LLIOPipe::buffer_ptr_t& buffer) -{ -	mProcessed = true; - -	// thread could have already be destroyed during logout -	if( !gMeshRepo.mThread ) -	{ -		return; -	} - -	if (status < 200 || status > 400) -	{ -		//llwarns -		//	<< "Header responder failed with status: " -		//	<< status << ": " << reason << llendl; - -		// 503 (service unavailable) or 499 (timeout) -		// can be due to server load and can be retried - -		// TODO*: Add maximum retry logic, exponential backoff -		// and (somewhat more optional than the others) retries -		// again after some set period of time - -		llassert(status == 503 || status == 499); - -		if (status == 503 || status == 499) -		{ //retry -			llwarns << "Timeout or service unavailable, retrying." << llendl; -			LLMeshRepository::sHTTPRetryCount++; -			LLMeshRepoThread::HeaderRequest req(mMeshParams); -			LLMutexLock lock(gMeshRepo.mThread->mMutex); -			gMeshRepo.mThread->mHeaderReqQ.push(req); - -			return; -		} -		else -		{ -			llwarns << "Unhandled status." << llendl; -		} -	} - -	S32 data_size = buffer->countAfter(channels.in(), NULL); - -	U8* data = NULL; - -	if (data_size > 0) -	{ -		data = new U8[data_size]; -		buffer->readAfter(channels.in(), NULL, data, data_size); -	} - -	LLMeshRepository::sBytesReceived += llmin(data_size, MESH_HEADER_SIZE); - -	bool success = gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size); -	 -	llassert(success); - -	if (!success) -	{ -		llwarns -			<< "Unable to parse mesh header: " -			<< status << ": " << reason << llendl; -	} -	else if (data && data_size > 0) -	{ -		//header was successfully retrieved from sim, cache in vfs -		LLUUID mesh_id = mMeshParams.getSculptID(); -		LLSD header = gMeshRepo.mThread->mMeshHeader[mesh_id]; - -		S32 version = header["version"].asInteger(); - -		if (version <= MAX_MESH_VERSION) -		{ -			std::stringstream str; - -			S32 lod_bytes = 0; - -			for (U32 i = 0; i < LLModel::LOD_PHYSICS; ++i) -			{ //figure out how many bytes we'll need to reserve in the file -				std::string lod_name = header_lod[i]; -				lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger()); -			} -		 -			//just in case skin info or decomposition is at the end of the file (which it shouldn't be) -			lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger()); -			lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger()); - -			S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; -			S32 bytes = lod_bytes + header_bytes;  - -		 -			//it's possible for the remote asset to have more data than is needed for the local cache -			//only allocate as much space in the VFS as is needed for the local cache -			data_size = llmin(data_size, bytes); - -			LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH, LLVFile::WRITE); -			if (file.getMaxSize() >= bytes || file.setMaxSize(bytes)) -			{ -				LLMeshRepository::sCacheBytesWritten += data_size; - -				file.write((const U8*) data, data_size); -			 -				//zero out the rest of the file  -				U8 block[MESH_HEADER_SIZE]; -				memset(block, 0, MESH_HEADER_SIZE); - -				while (bytes-file.tell() > MESH_HEADER_SIZE) -				{ -					file.write(block, MESH_HEADER_SIZE); -				} - -				S32 remaining = bytes-file.tell(); - -				if (remaining > 0) -				{ -					file.write(block, remaining); -				} -			} -		} -	} - -	delete [] data; -} - -  LLMeshRepository::LLMeshRepository()  : mMeshMutex(NULL),    mMeshThreadCount(0), @@ -4310,9 +3821,9 @@ void LLMeshRepository::metricsProgress(unsigned int this_count)  void LLMeshRepository::metricsUpdate()  {  	F64 started, stopped; -	U64 total_count; - -	if (sQuiescentTimer.isExpired(0, started, stopped, total_count)) +	U64 total_count(U64L(0)), user_cpu(U64L(0)), sys_cpu(U64L(0)); +	 +	if (sQuiescentTimer.isExpired(0, started, stopped, total_count, user_cpu, sys_cpu))  	{  		LLSD metrics; @@ -4322,6 +3833,8 @@ void LLMeshRepository::metricsUpdate()  		metrics["stop"] = stopped;  		metrics["downloads"] = LLSD::Integer(total_count);  		metrics["teleports"] = LLSD::Integer(metrics_teleport_start_count); +		metrics["user_cpu"] = double(user_cpu) / 1.0e6; +		metrics["sys_cpu"] = double(sys_cpu) / 1.0e6;  		llinfos << "EventMarker " << metrics << llendl;  	}  } @@ -4377,103 +3890,6 @@ bool is_retryable(LLCore::HttpStatus status)  //  //  #if 0 -	  mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), -	mHttpRequest = new LLCore::HttpRequest; -	mHttpOptions = new LLCore::HttpOptions; -	mHttpHeaders = new LLCore::HttpHeaders; -	mHttpHeaders->mHeaders.push_back("Accept: image/x-j2c"); -	mHttpMetricsHeaders = new LLCore::HttpHeaders; -	mHttpMetricsHeaders->mHeaders.push_back("Content-Type: application/llsd+xml"); -	mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault(); - - -	LLCore::HttpHandle		mHttpHandle;				// Handle of any active request -	LLCore::BufferArray	*	mHttpBufferArray;			// Refcounted pointer to response data  -	int						mHttpPolicyClass; -	bool					mHttpActive;				// Active request to http library -	unsigned int			mHttpReplySize;				// Actual received data size -	unsigned int			mHttpReplyOffset;			// Actual received data offset -	bool					mHttpHasResource;			// Counts against Fetcher's mHttpSemaphore - -									  -		mHttpHandle = LLCORE_HTTP_HANDLE_INVALID; -		if (!mUrl.empty()) -		{ -			mRequestedTimer.reset(); -			mLoaded = FALSE; -			mGetStatus = LLCore::HttpStatus(); -			mGetReason.clear(); -			LL_DEBUGS("Texture") << "HTTP GET: " << mID << " Offset: " << mRequestedOffset -								 << " Bytes: " << mRequestedSize -								 << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << mFetcher->mMaxBandwidth -								 << LL_ENDL; - -			// Will call callbackHttpGet when curl request completes -			mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass, -																	  mWorkPriority, -																	  mUrl, -																	  mRequestedOffset, -																	  mRequestedSize, -																	  mFetcher->mHttpOptions, -																	  mFetcher->mHttpHeaders, -																	  this); -		} -		if (LLCORE_HTTP_HANDLE_INVALID == mHttpHandle) -		{ -			llwarns << "HTTP GET request failed for " << mID << llendl; -			resetFormattedData(); -			releaseHttpSemaphore(); -			return true; // failed -		} - -		mHttpActive = true; -		mFetcher->addToHTTPQueue(mID); -		recordTextureStart(true); -		setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); -		mState = WAIT_HTTP_REQ;	 -		 -		// fall through -	} - - - -// Threads:  Ttf -// virtual -void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response) -{ -	static LLCachedControl<bool> log_to_viewer_log(gSavedSettings, "LogTextureDownloadsToViewerLog"); -	static LLCachedControl<bool> log_to_sim(gSavedSettings, "LogTextureDownloadsToSimulator"); -	static LLCachedControl<bool> log_texture_traffic(gSavedSettings, "LogTextureNetworkTraffic") ; - -	LLMutexLock lock(&mWorkMutex);										// +Mw - -	mHttpActive = false; -	 -	if (log_to_viewer_log || log_to_sim) -	{ -		U64 timeNow = LLTimer::getTotalTime(); -		mFetcher->mTextureInfo.setRequestStartTime(mID, mMetricsStartTime); -		mFetcher->mTextureInfo.setRequestType(mID, LLTextureInfoDetails::REQUEST_TYPE_HTTP); -		mFetcher->mTextureInfo.setRequestSize(mID, mRequestedSize); -		mFetcher->mTextureInfo.setRequestOffset(mID, mRequestedOffset); -		mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); -	} - -	bool success = true; -	bool partial = false; -	LLCore::HttpStatus status(response->getStatus()); -	 -	lldebugs << "HTTP COMPLETE: " << mID -			 << " status: " << status.toHex() -			 << " '" << status.toString() << "'" -			 << llendl; -//	unsigned int offset(0), length(0), full_length(0); -//	response->getRange(&offset, &length, &full_length); -// 	llwarns << "HTTP COMPLETE: " << mID << " handle: " << handle -// 			<< " status: " << status.toULong() << " '" << status.toString() << "'" -// 			<< " req offset: " << mRequestedOffset << " req length: " << mRequestedSize -// 			<< " offset: " << offset << " length: " << length -// 			<< llendl;  	if (! status)  	{ @@ -4497,19 +3913,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe  	S32 data_size = callbackHttpGet(response, partial, success); -	if (log_texture_traffic && data_size > 0) -	{ -		LLViewerTexture* tex = LLViewerTextureManager::findTexture(mID); -		if (tex) -		{ -			gTotalTextureBytesPerBoostLevel[tex->getBoostLevel()] += data_size ; -		} -	} -	mFetcher->removeFromHTTPQueue(mID, data_size); -	 -	recordTextureDone(true); -}																		// -Mw  // Threads:  Ttf  | 
