From c7b082eac204380d805350ab73ffea470ee4f56a Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Tue, 5 Oct 2010 14:11:57 -0700 Subject: Add new repo to build definitions. --- BuildParams | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/BuildParams b/BuildParams index 898cb7bbd3..6896786748 100644 --- a/BuildParams +++ b/BuildParams @@ -185,5 +185,13 @@ viewer-tut-teamcity.email = enus@lindenlab.com viewer-tut-teamcity.build_server = false viewer-tut-teamcity.build_server_tests = false +# ================================================================= +# asset delivery 2010 projects +# ================================================================= +viewer-asset-delivery.viewer_channel = "Second Life Development" +viewer-asset-delivery.login_channel = "Second Life Development" +viewer-asset-delivery.build_viewer_update_version_manager = false +viewer-asset-delivery.email = monty@lindenlab.com + # eof -- cgit v1.2.3 From 90168d285bfa0250cab6709eb3be8d6f2517011a Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Fri, 22 Oct 2010 09:10:44 -0700 Subject: ESC-108 Develop support classes for numerical collection Stuff moved over and adapted from simulator code. Basic, simple counters and min/max/mean accumulators. --- indra/newview/CMakeLists.txt | 5 + indra/newview/llsimplestat.h | 140 ++++++++++ indra/newview/tests/llsimplestat_test.cpp | 428 ++++++++++++++++++++++++++++++ 3 files changed, 573 insertions(+) create mode 100644 indra/newview/llsimplestat.h create mode 100644 indra/newview/tests/llsimplestat_test.cpp diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 1f4302d870..0c4d2aaca6 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1925,6 +1925,11 @@ if (LL_TESTS) "${test_libs}" ) + LL_ADD_INTEGRATION_TEST(llsimplestat + "" + "${test_libs}" + ) + #ADD_VIEWER_BUILD_TEST(llmemoryview viewer) #ADD_VIEWER_BUILD_TEST(llagentaccess viewer) #ADD_VIEWER_BUILD_TEST(llworldmap viewer) diff --git a/indra/newview/llsimplestat.h b/indra/newview/llsimplestat.h new file mode 100644 index 0000000000..f8f4be0390 --- /dev/null +++ b/indra/newview/llsimplestat.h @@ -0,0 +1,140 @@ +/** + * @file llsimplestat.h + * @brief Runtime statistics accumulation. + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_SIMPLESTAT_H +#define LL_SIMPLESTAT_H + +// History +// +// The original source for this code is the server repositories' +// llcommon/llstat.h file. This particular code was added after the +// viewer/server code schism but before the effort to convert common +// code to libraries was complete. Rather than add to merge issues, +// the needed code was cut'n'pasted into this new header as it isn't +// too awful a burden. Post-modularization, we can look at removing +// this redundancy. + + +/** + * @class LLSimpleStatCounter + * @brief Just counts events. + * + * Really not needed but have a pattern in mind in the future. + * Interface limits what can be done at that's just fine. + * + * *TODO: Update/transfer unit tests + * Unit tests: indra/test/llcommon_llstat_tut.cpp + */ +class LLSimpleStatCounter +{ +public: + inline LLSimpleStatCounter() { reset(); } + // Default destructor and assignment operator are valid + + inline void reset() { mCount = 0; } + + inline U32 operator++() { return ++mCount; } + + inline U32 getCount() const { return mCount; } + +protected: + U32 mCount; +}; + + +/** + * @class LLSimpleStatMMM + * @brief Templated collector of min, max and mean data for stats. + * + * Fed a stream of data samples, keeps a running account of the + * min, max and mean seen since construction or the last reset() + * call. A freshly-constructed or reset instance returns counts + * and values of zero. + * + * Overflows and underflows (integer, inf or -inf) and NaN's + * are the caller's problem. As is loss of precision when + * the running sum's exponent (when parameterized by a floating + * point of some type) differs from a given data sample's. + * + * Unit tests: indra/test/llcommon_llstat_tut.cpp + */ +template +class LLSimpleStatMMM +{ +public: + typedef VALUE_T Value; + +public: + LLSimpleStatMMM() { reset(); } + // Default destructor and assignment operator are valid + + /** + * Resets the object returning all counts and derived + * values back to zero. + */ + void reset() + { + mCount = 0; + mMin = Value(0); + mMax = Value(0); + mTotal = Value(0); + } + + void record(Value v) + { + if (mCount) + { + mMin = llmin(mMin, v); + mMax = llmax(mMax, v); + } + else + { + mMin = v; + mMax = v; + } + mTotal += v; + ++mCount; + } + + inline U32 getCount() const { return mCount; } + inline Value getMin() const { return mMin; } + inline Value getMax() const { return mMax; } + inline Value getMean() const { return mCount ? mTotal / mCount : mTotal; } + +protected: + U32 mCount; + Value mMin; + Value mMax; + Value mTotal; +}; + +#endif // LL_SIMPLESTAT_H diff --git a/indra/newview/tests/llsimplestat_test.cpp b/indra/newview/tests/llsimplestat_test.cpp new file mode 100644 index 0000000000..5efc9cf857 --- /dev/null +++ b/indra/newview/tests/llsimplestat_test.cpp @@ -0,0 +1,428 @@ +/** + * @file llsimplestats_test.cpp + * @date 2010-10-22 + * @brief Test cases for some of llsimplestat.h + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include + +#include "lltut.h" +#include "../llsimplestat.h" +#include "llsd.h" +#include "llmath.h" + +// @brief Used as a pointer cast type to get access to LLSimpleStatCounter +class TutStatCounter: public LLSimpleStatCounter +{ +public: + TutStatCounter(); // Not defined + ~TutStatCounter(); // Not defined + void operator=(const TutStatCounter &); // Not defined + + void setRawCount(U32 c) { mCount = c; } + U32 getRawCount() const { return mCount; } +}; + + +namespace tut +{ + struct stat_counter_index + {}; + typedef test_group stat_counter_index_t; + typedef stat_counter_index_t::object stat_counter_index_object_t; + tut::stat_counter_index_t tut_stat_counter_index("stat_counter_test"); + + // Testing LLSimpleStatCounter's external interface + template<> template<> + void stat_counter_index_object_t::test<1>() + { + LLSimpleStatCounter c1; + ensure("Initialized counter is zero", (0 == c1.getCount())); + + ensure("Counter increment return is 1", (1 == ++c1)); + ensure("Counter increment return is 2", (2 == ++c1)); + + ensure("Current counter is 2", (2 == c1.getCount())); + + c1.reset(); + ensure("Counter is 0 after reset", (0 == c1.getCount())); + + ensure("Counter increment return is 1", (1 == ++c1)); + } + + // Testing LLSimpleStatCounter's internal state + template<> template<> + void stat_counter_index_object_t::test<2>() + { + LLSimpleStatCounter c1; + TutStatCounter * tc1 = (TutStatCounter *) &c1; + + ensure("Initialized private counter is zero", (0 == tc1->getRawCount())); + + ++c1; + ++c1; + + ensure("Current private counter is 2", (2 == tc1->getRawCount())); + + c1.reset(); + ensure("Raw counter is 0 after reset", (0 == tc1->getRawCount())); + } + + // Testing LLSimpleStatCounter's wrapping behavior + template<> template<> + void stat_counter_index_object_t::test<3>() + { + LLSimpleStatCounter c1; + TutStatCounter * tc1 = (TutStatCounter *) &c1; + + tc1->setRawCount(U32_MAX); + ensure("Initialized private counter is zero", (U32_MAX == c1.getCount())); + + ensure("Increment of max value wraps to 0", (0 == ++c1)); + } + + // Testing LLSimpleStatMMM's external behavior + template<> template<> + void stat_counter_index_object_t::test<4>() + { + LLSimpleStatMMM<> m1; + typedef LLSimpleStatMMM<>::Value lcl_float; + lcl_float zero(0); + + // Freshly-constructed + ensure("Constructed MMM<> has 0 count", (0 == m1.getCount())); + ensure("Constructed MMM<> has 0 min", (zero == m1.getMin())); + ensure("Constructed MMM<> has 0 max", (zero == m1.getMax())); + ensure("Constructed MMM<> has 0 mean no div-by-zero", (zero == m1.getMean())); + + // Single insert + m1.record(1.0); + ensure("Single insert MMM<> has 1 count", (1 == m1.getCount())); + ensure("Single insert MMM<> has 1.0 min", (1.0 == m1.getMin())); + ensure("Single insert MMM<> has 1.0 max", (1.0 == m1.getMax())); + ensure("Single insert MMM<> has 1.0 mean", (1.0 == m1.getMean())); + + // Second insert + m1.record(3.0); + ensure("2nd insert MMM<> has 2 count", (2 == m1.getCount())); + ensure("2nd insert MMM<> has 1.0 min", (1.0 == m1.getMin())); + ensure("2nd insert MMM<> has 3.0 max", (3.0 == m1.getMax())); + ensure_approximately_equals("2nd insert MMM<> has 2.0 mean", m1.getMean(), lcl_float(2.0), 1); + + // Third insert + m1.record(5.0); + ensure("3rd insert MMM<> has 3 count", (3 == m1.getCount())); + ensure("3rd insert MMM<> has 1.0 min", (1.0 == m1.getMin())); + ensure("3rd insert MMM<> has 5.0 max", (5.0 == m1.getMax())); + ensure_approximately_equals("3rd insert MMM<> has 3.0 mean", m1.getMean(), lcl_float(3.0), 1); + + // Fourth insert + m1.record(1000000.0); + ensure("4th insert MMM<> has 4 count", (4 == m1.getCount())); + ensure("4th insert MMM<> has 1.0 min", (1.0 == m1.getMin())); + ensure("4th insert MMM<> has 100000.0 max", (1000000.0 == m1.getMax())); + ensure_approximately_equals("4th insert MMM<> has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1); + + // Reset + m1.reset(); + ensure("Reset MMM<> has 0 count", (0 == m1.getCount())); + ensure("Reset MMM<> has 0 min", (zero == m1.getMin())); + ensure("Reset MMM<> has 0 max", (zero == m1.getMax())); + ensure("Reset MMM<> has 0 mean no div-by-zero", (zero == m1.getMean())); + } + + // Testing LLSimpleStatMMM's response to large values + template<> template<> + void stat_counter_index_object_t::test<5>() + { + LLSimpleStatMMM<> m1; + typedef LLSimpleStatMMM<>::Value lcl_float; + lcl_float zero(0); + + // Insert overflowing values + const lcl_float bignum(F32_MAX / 2); + + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(zero); + + ensure("Overflowed MMM<> has 8 count", (8 == m1.getCount())); + ensure("Overflowed MMM<> has 0 min", (zero == m1.getMin())); + ensure("Overflowed MMM<> has huge max", (bignum == m1.getMax())); + ensure("Overflowed MMM<> has fetchable mean", (1.0 == m1.getMean() || true)); + // We should be infinte but not interested in proving the IEEE standard here. + LLSD sd1(m1.getMean()); + // std::cout << "Thingy: " << m1.getMean() << " and as LLSD: " << sd1 << std::endl; + ensure("Overflowed MMM<> produces LLSDable Real", (sd1.isReal())); + } + + // Testing LLSimpleStatMMM's external behavior + template<> template<> + void stat_counter_index_object_t::test<6>() + { + LLSimpleStatMMM m1; + typedef LLSimpleStatMMM::Value lcl_float; + lcl_float zero(0); + + // Freshly-constructed + ensure("Constructed MMM has 0 count", (0 == m1.getCount())); + ensure("Constructed MMM has 0 min", (zero == m1.getMin())); + ensure("Constructed MMM has 0 max", (zero == m1.getMax())); + ensure("Constructed MMM has 0 mean no div-by-zero", (zero == m1.getMean())); + + // Single insert + m1.record(1.0); + ensure("Single insert MMM has 1 count", (1 == m1.getCount())); + ensure("Single insert MMM has 1.0 min", (1.0 == m1.getMin())); + ensure("Single insert MMM has 1.0 max", (1.0 == m1.getMax())); + ensure("Single insert MMM has 1.0 mean", (1.0 == m1.getMean())); + + // Second insert + m1.record(3.0); + ensure("2nd insert MMM has 2 count", (2 == m1.getCount())); + ensure("2nd insert MMM has 1.0 min", (1.0 == m1.getMin())); + ensure("2nd insert MMM has 3.0 max", (3.0 == m1.getMax())); + ensure_approximately_equals("2nd insert MMM has 2.0 mean", m1.getMean(), lcl_float(2.0), 1); + + // Third insert + m1.record(5.0); + ensure("3rd insert MMM has 3 count", (3 == m1.getCount())); + ensure("3rd insert MMM has 1.0 min", (1.0 == m1.getMin())); + ensure("3rd insert MMM has 5.0 max", (5.0 == m1.getMax())); + ensure_approximately_equals("3rd insert MMM has 3.0 mean", m1.getMean(), lcl_float(3.0), 1); + + // Fourth insert + m1.record(1000000.0); + ensure("4th insert MMM has 4 count", (4 == m1.getCount())); + ensure("4th insert MMM has 1.0 min", (1.0 == m1.getMin())); + ensure("4th insert MMM has 1000000.0 max", (1000000.0 == m1.getMax())); + ensure_approximately_equals("4th insert MMM has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1); + + // Reset + m1.reset(); + ensure("Reset MMM has 0 count", (0 == m1.getCount())); + ensure("Reset MMM has 0 min", (zero == m1.getMin())); + ensure("Reset MMM has 0 max", (zero == m1.getMax())); + ensure("Reset MMM has 0 mean no div-by-zero", (zero == m1.getMean())); + } + + // Testing LLSimpleStatMMM's response to large values + template<> template<> + void stat_counter_index_object_t::test<7>() + { + LLSimpleStatMMM m1; + typedef LLSimpleStatMMM::Value lcl_float; + lcl_float zero(0); + + // Insert overflowing values + const lcl_float bignum(F32_MAX / 2); + + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(zero); + + ensure("Overflowed MMM has 8 count", (8 == m1.getCount())); + ensure("Overflowed MMM has 0 min", (zero == m1.getMin())); + ensure("Overflowed MMM has huge max", (bignum == m1.getMax())); + ensure("Overflowed MMM has fetchable mean", (1.0 == m1.getMean() || true)); + // We should be infinte but not interested in proving the IEEE standard here. + LLSD sd1(m1.getMean()); + // std::cout << "Thingy: " << m1.getMean() << " and as LLSD: " << sd1 << std::endl; + ensure("Overflowed MMM produces LLSDable Real", (sd1.isReal())); + } + + // Testing LLSimpleStatMMM's external behavior + template<> template<> + void stat_counter_index_object_t::test<8>() + { + LLSimpleStatMMM m1; + typedef LLSimpleStatMMM::Value lcl_float; + lcl_float zero(0); + + // Freshly-constructed + ensure("Constructed MMM has 0 count", (0 == m1.getCount())); + ensure("Constructed MMM has 0 min", (zero == m1.getMin())); + ensure("Constructed MMM has 0 max", (zero == m1.getMax())); + ensure("Constructed MMM has 0 mean no div-by-zero", (zero == m1.getMean())); + + // Single insert + m1.record(1.0); + ensure("Single insert MMM has 1 count", (1 == m1.getCount())); + ensure("Single insert MMM has 1.0 min", (1.0 == m1.getMin())); + ensure("Single insert MMM has 1.0 max", (1.0 == m1.getMax())); + ensure("Single insert MMM has 1.0 mean", (1.0 == m1.getMean())); + + // Second insert + m1.record(3.0); + ensure("2nd insert MMM has 2 count", (2 == m1.getCount())); + ensure("2nd insert MMM has 1.0 min", (1.0 == m1.getMin())); + ensure("2nd insert MMM has 3.0 max", (3.0 == m1.getMax())); + ensure_approximately_equals("2nd insert MMM has 2.0 mean", m1.getMean(), lcl_float(2.0), 1); + + // Third insert + m1.record(5.0); + ensure("3rd insert MMM has 3 count", (3 == m1.getCount())); + ensure("3rd insert MMM has 1.0 min", (1.0 == m1.getMin())); + ensure("3rd insert MMM has 5.0 max", (5.0 == m1.getMax())); + ensure_approximately_equals("3rd insert MMM has 3.0 mean", m1.getMean(), lcl_float(3.0), 1); + + // Fourth insert + m1.record(1000000.0); + ensure("4th insert MMM has 4 count", (4 == m1.getCount())); + ensure("4th insert MMM has 1.0 min", (1.0 == m1.getMin())); + ensure("4th insert MMM has 1000000.0 max", (1000000.0 == m1.getMax())); + ensure_approximately_equals("4th insert MMM has 250002.0 mean", m1.getMean(), lcl_float(250002.0), 1); + + // Reset + m1.reset(); + ensure("Reset MMM has 0 count", (0 == m1.getCount())); + ensure("Reset MMM has 0 min", (zero == m1.getMin())); + ensure("Reset MMM has 0 max", (zero == m1.getMax())); + ensure("Reset MMM has 0 mean no div-by-zero", (zero == m1.getMean())); + } + + // Testing LLSimpleStatMMM's response to large values + template<> template<> + void stat_counter_index_object_t::test<9>() + { + LLSimpleStatMMM m1; + typedef LLSimpleStatMMM::Value lcl_float; + lcl_float zero(0); + + // Insert overflowing values + const lcl_float bignum(F64_MAX / 2); + + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(zero); + + ensure("Overflowed MMM has 8 count", (8 == m1.getCount())); + ensure("Overflowed MMM has 0 min", (zero == m1.getMin())); + ensure("Overflowed MMM has huge max", (bignum == m1.getMax())); + ensure("Overflowed MMM has fetchable mean", (1.0 == m1.getMean() || true)); + // We should be infinte but not interested in proving the IEEE standard here. + LLSD sd1(m1.getMean()); + // std::cout << "Thingy: " << m1.getMean() << " and as LLSD: " << sd1 << std::endl; + ensure("Overflowed MMM produces LLSDable Real", (sd1.isReal())); + } + + // Testing LLSimpleStatMMM's external behavior + template<> template<> + void stat_counter_index_object_t::test<10>() + { + LLSimpleStatMMM m1; + typedef LLSimpleStatMMM::Value lcl_int; + lcl_int zero(0); + + // Freshly-constructed + ensure("Constructed MMM has 0 count", (0 == m1.getCount())); + ensure("Constructed MMM has 0 min", (zero == m1.getMin())); + ensure("Constructed MMM has 0 max", (zero == m1.getMax())); + ensure("Constructed MMM has 0 mean no div-by-zero", (zero == m1.getMean())); + + // Single insert + m1.record(1); + ensure("Single insert MMM has 1 count", (1 == m1.getCount())); + ensure("Single insert MMM has 1 min", (1 == m1.getMin())); + ensure("Single insert MMM has 1 max", (1 == m1.getMax())); + ensure("Single insert MMM has 1 mean", (1 == m1.getMean())); + + // Second insert + m1.record(3); + ensure("2nd insert MMM has 2 count", (2 == m1.getCount())); + ensure("2nd insert MMM has 1 min", (1 == m1.getMin())); + ensure("2nd insert MMM has 3 max", (3 == m1.getMax())); + ensure("2nd insert MMM has 2 mean", (2 == m1.getMean())); + + // Third insert + m1.record(5); + ensure("3rd insert MMM has 3 count", (3 == m1.getCount())); + ensure("3rd insert MMM has 1 min", (1 == m1.getMin())); + ensure("3rd insert MMM has 5 max", (5 == m1.getMax())); + ensure("3rd insert MMM has 3 mean", (3 == m1.getMean())); + + // Fourth insert + m1.record(U64L(1000000000000)); + ensure("4th insert MMM has 4 count", (4 == m1.getCount())); + ensure("4th insert MMM has 1 min", (1 == m1.getMin())); + ensure("4th insert MMM has 1000000000000ULL max", (U64L(1000000000000) == m1.getMax())); + ensure("4th insert MMM has 250000000002ULL mean", (U64L( 250000000002) == m1.getMean())); + + // Reset + m1.reset(); + ensure("Reset MMM has 0 count", (0 == m1.getCount())); + ensure("Reset MMM has 0 min", (zero == m1.getMin())); + ensure("Reset MMM has 0 max", (zero == m1.getMax())); + ensure("Reset MMM has 0 mean no div-by-zero", (zero == m1.getMean())); + } + + // Testing LLSimpleStatMMM's response to large values + template<> template<> + void stat_counter_index_object_t::test<11>() + { + LLSimpleStatMMM m1; + typedef LLSimpleStatMMM::Value lcl_int; + lcl_int zero(0); + + // Insert overflowing values + const lcl_int bignum(U64L(0xffffffffffffffff) / 2); + + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(bignum); + m1.record(zero); + + ensure("Overflowed MMM has 8 count", (8 == m1.getCount())); + ensure("Overflowed MMM has 0 min", (zero == m1.getMin())); + ensure("Overflowed MMM has huge max", (bignum == m1.getMax())); + ensure("Overflowed MMM has fetchable mean", (zero == m1.getMean() || true)); + } +} -- cgit v1.2.3 From dac53830f1a67c8657ced9c39eccedbadf149bd9 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Wed, 27 Oct 2010 23:40:35 -0700 Subject: STORM-104 : make kdu statically linked, suppress the need for llkdu --- indra/cmake/Copy3rdPartyLibs.cmake | 81 ----------- indra/cmake/LLKDU.cmake | 19 ++- .../integration_tests/llui_libtest/CMakeLists.txt | 2 + indra/llimage/CMakeLists.txt | 1 - indra/llimage/llimage.cpp | 2 - indra/llimage/llimagej2c.cpp | 162 +-------------------- indra/llimage/llimagej2c.h | 2 - indra/newview/CMakeLists.txt | 18 ++- install.xml | 19 ++- 9 files changed, 51 insertions(+), 255 deletions(-) diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 95ed5d6bc8..e0d634dad2 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -59,22 +59,6 @@ if(WINDOWS) set(fmod_files fmod.dll) endif (FMOD_SDK_DIR) - #******************************* - # LLKDU - set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu") - if(NOT EXISTS ${internal_llkdu_path}) - if (EXISTS "${debug_src_dir}/llkdu.dll") - set(debug_llkdu_src "${debug_src_dir}/llkdu.dll") - set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/llkdu.dll") - endif (EXISTS "${debug_src_dir}/llkdu.dll") - - if (EXISTS "${release_src_dir}/llkdu.dll") - set(release_llkdu_src "${release_src_dir}/llkdu.dll") - set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/llkdu.dll") - set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/llkdu.dll") - endif (EXISTS "${release_src_dir}/llkdu.dll") - endif (NOT EXISTS ${internal_llkdu_path}) - #******************************* # Copy MS C runtime dlls, required for packaging. # *TODO - Adapt this to support VC9 @@ -173,21 +157,6 @@ elseif(DARWIN) # fmod is statically linked on darwin set(fmod_files "") - #******************************* - # LLKDU - set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu") - if(NOT EXISTS ${internal_llkdu_path}) - if (EXISTS "${debug_src_dir}/libllkdu.dylib") - set(debug_llkdu_src "${debug_src_dir}/libllkdu.dylib") - set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/libllkdu.dylib") - endif (EXISTS "${debug_src_dir}/libllkdu.dylib") - - if (EXISTS "${release_src_dir}/libllkdu.dylib") - set(release_llkdu_src "${release_src_dir}/libllkdu.dylib") - set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/libllkdu.dylib") - set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/libllkdu.dylib") - endif (EXISTS "${release_src_dir}/libllkdu.dylib") - endif (NOT EXISTS ${internal_llkdu_path}) elseif(LINUX) # linux is weird, multiple side by side configurations aren't supported # and we don't seem to have any debug shared libs built yet anyways... @@ -241,21 +210,6 @@ elseif(LINUX) set(fmod_files "libfmod-3.75.so") endif (FMOD_SDK_DIR) - #******************************* - # LLKDU - set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu") - if(NOT EXISTS ${internal_llkdu_path}) - if (EXISTS "${debug_src_dir}/libllkdu.so") - set(debug_llkdu_src "${debug_src_dir}/libllkdu.so") - set(debug_llkdu_dst "${SHARED_LIB_STAGING_DIR_DEBUG}/libllkdu.so") - endif (EXISTS "${debug_src_dir}/libllkdu.so") - - if (EXISTS "${release_src_dir}/libllkdu.so") - set(release_llkdu_src "${release_src_dir}/libllkdu.so") - set(release_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELEASE}/libllkdu.so") - set(relwithdebinfo_llkdu_dst "${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}/libllkdu.so") - endif (EXISTS "${release_src_dir}/libllkdu.so") - endif(NOT EXISTS ${internal_llkdu_path}) else(WINDOWS) message(STATUS "WARNING: unrecognized platform for staging 3rd party libs, skipping...") set(vivox_src_dir "${CMAKE_SOURCE_DIR}/newview/vivox-runtime/i686-linux") @@ -357,41 +311,6 @@ if (FMOD_SDK_DIR) set(all_targets ${all_targets} ${out_targets}) endif (FMOD_SDK_DIR) -#******************************* -# LLKDU -set(internal_llkdu_path "${CMAKE_SOURCE_DIR}/llkdu") -if(NOT EXISTS ${internal_llkdu_path}) - if (EXISTS "${debug_llkdu_src}") - ADD_CUSTOM_COMMAND( - OUTPUT ${debug_llkdu_dst} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${debug_llkdu_src} ${debug_llkdu_dst} - DEPENDS ${debug_llkdu_src} - COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_DEBUG}" - ) - set(third_party_targets ${third_party_targets} $} ${debug_llkdu_dst}) - endif (EXISTS "${debug_llkdu_src}") - - if (EXISTS "${release_llkdu_src}") - ADD_CUSTOM_COMMAND( - OUTPUT ${release_llkdu_dst} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${release_llkdu_src} ${release_llkdu_dst} - DEPENDS ${release_llkdu_src} - COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_RELEASE}" - ) - set(third_party_targets ${third_party_targets} ${release_llkdu_dst}) - - ADD_CUSTOM_COMMAND( - OUTPUT ${relwithdebinfo_llkdu_dst} - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${release_llkdu_src} ${relwithdebinfo_llkdu_dst} - DEPENDS ${release_llkdu_src} - COMMENT "Copying llkdu.dll ${SHARED_LIB_STAGING_DIR_RELWITHDEBINFO}" - ) - set(third_party_targets ${third_party_targets} ${relwithdebinfo_llkdu_dst}) - endif (EXISTS "${release_llkdu_src}") - -endif (NOT EXISTS ${internal_llkdu_path}) - - if(NOT STANDALONE) add_custom_target( stage_third_party_libs ALL diff --git a/indra/cmake/LLKDU.cmake b/indra/cmake/LLKDU.cmake index 27c8ada686..25703ee785 100644 --- a/indra/cmake/LLKDU.cmake +++ b/indra/cmake/LLKDU.cmake @@ -1,7 +1,24 @@ # -*- cmake -*- include(Prebuilt) +# USE_KDU can be set when launching cmake or develop.py as an option using the argument -DUSE_KDU:BOOL=ON +# When building using proprietary binaries though (i.e. having access to LL private servers), we always build with KDU if (INSTALL_PROPRIETARY AND NOT STANDALONE) + set(USE_KDU ON) +endif (INSTALL_PROPRIETARY AND NOT STANDALONE) + +if (USE_KDU) use_prebuilt_binary(kdu) + if (WINDOWS) + set(KDU_LIBRARY debug kdu_cored optimized kdu_core) + else (WINDOWS) + set(KDU_LIBRARY kdu) + endif (WINDOWS) + + set(KDU_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) + set(LLKDU_LIBRARY llkdu) -endif (INSTALL_PROPRIETARY AND NOT STANDALONE) + set(LLKDU_STATIC_LIBRARY llkdu_static) + set(LLKDU_LIBRARIES ${LLKDU_LIBRARY}) + set(LLKDU_STATIC_LIBRARIES ${LLKDU_STATIC_LIBRARY}) +endif (USE_KDU) diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt index 452d37d3be..2a00dbee6f 100644 --- a/indra/integration_tests/llui_libtest/CMakeLists.txt +++ b/indra/integration_tests/llui_libtest/CMakeLists.txt @@ -71,6 +71,8 @@ endif (DARWIN) target_link_libraries(llui_libtest llui llmessage + ${LLIMAGE_LIBRARIES} + ${LLIMAGEJ2COJ_LIBRARIES} ${OS_LIBRARIES} ${GOOGLE_PERFTOOLS_LIBRARIES} ) diff --git a/indra/llimage/CMakeLists.txt b/indra/llimage/CMakeLists.txt index a69621a57b..6834267d4b 100644 --- a/indra/llimage/CMakeLists.txt +++ b/indra/llimage/CMakeLists.txt @@ -57,7 +57,6 @@ add_library (llimage ${llimage_SOURCE_FILES}) # Sort by high-level to low-level target_link_libraries(llimage llcommon - llimagej2coj # *HACK: In theory a noop for KDU builds? ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 5c33b675ca..b46a99e030 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -52,13 +52,11 @@ LLMutex* LLImage::sMutex = NULL; void LLImage::initClass() { sMutex = new LLMutex(NULL); - LLImageJ2C::openDSO(); } //static void LLImage::cleanupClass() { - LLImageJ2C::closeDSO(); delete sMutex; sMutex = NULL; } diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 207728d4d9..840813fa75 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -24,9 +24,6 @@ */ #include "linden_common.h" -#include "apr_pools.h" -#include "apr_dso.h" - #include "lldir.h" #include "llimagej2c.h" #include "llmemtype.h" @@ -36,18 +33,10 @@ typedef LLImageJ2CImpl* (*CreateLLImageJ2CFunction)(); typedef void (*DestroyLLImageJ2CFunction)(LLImageJ2CImpl*); typedef const char* (*EngineInfoLLImageJ2CFunction)(); -//some "private static" variables so we only attempt to load -//dynamic libaries once -CreateLLImageJ2CFunction j2cimpl_create_func; -DestroyLLImageJ2CFunction j2cimpl_destroy_func; -EngineInfoLLImageJ2CFunction j2cimpl_engineinfo_func; -apr_pool_t *j2cimpl_dso_memory_pool; -apr_dso_handle_t *j2cimpl_dso_handle; - -//Declare the prototype for theses functions here, their functionality -//will be implemented in other files which define a derived LLImageJ2CImpl -//but only ONE static library which has the implementation for this -//function should ever be included +// Declare the prototype for theses functions here. Their functionality +// will be implemented in other files which define a derived LLImageJ2CImpl +// but only ONE static library which has the implementation for these +// functions should ever be included. LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl(); void fallbackDestroyLLImageJ2CImpl(LLImageJ2CImpl* impl); const char* fallbackEngineInfoLLImageJ2CImpl(); @@ -55,121 +44,10 @@ const char* fallbackEngineInfoLLImageJ2CImpl(); // Test data gathering handle LLImageCompressionTester* LLImageJ2C::sTesterp = NULL ; -//static -//Loads the required "create", "destroy" and "engineinfo" functions needed -void LLImageJ2C::openDSO() -{ - //attempt to load a DSO and get some functions from it - std::string dso_name; - std::string dso_path; - - bool all_functions_loaded = false; - apr_status_t rv; - -#if LL_WINDOWS - dso_name = "llkdu.dll"; -#elif LL_DARWIN - dso_name = "libllkdu.dylib"; -#else - dso_name = "libllkdu.so"; -#endif - - dso_path = gDirUtilp->findFile(dso_name, - gDirUtilp->getAppRODataDir(), - gDirUtilp->getExecutableDir()); - - j2cimpl_dso_handle = NULL; - j2cimpl_dso_memory_pool = NULL; - - //attempt to load the shared library - apr_pool_create(&j2cimpl_dso_memory_pool, NULL); - rv = apr_dso_load(&j2cimpl_dso_handle, - dso_path.c_str(), - j2cimpl_dso_memory_pool); - - //now, check for success - if ( rv == APR_SUCCESS ) - { - //found the dynamic library - //now we want to load the functions we're interested in - CreateLLImageJ2CFunction create_func = NULL; - DestroyLLImageJ2CFunction dest_func = NULL; - EngineInfoLLImageJ2CFunction engineinfo_func = NULL; - - rv = apr_dso_sym((apr_dso_handle_sym_t*)&create_func, - j2cimpl_dso_handle, - "createLLImageJ2CKDU"); - if ( rv == APR_SUCCESS ) - { - //we've loaded the create function ok - //we need to delete via the DSO too - //so lets check for a destruction function - rv = apr_dso_sym((apr_dso_handle_sym_t*)&dest_func, - j2cimpl_dso_handle, - "destroyLLImageJ2CKDU"); - if ( rv == APR_SUCCESS ) - { - //we've loaded the destroy function ok - rv = apr_dso_sym((apr_dso_handle_sym_t*)&engineinfo_func, - j2cimpl_dso_handle, - "engineInfoLLImageJ2CKDU"); - if ( rv == APR_SUCCESS ) - { - //ok, everything is loaded alright - j2cimpl_create_func = create_func; - j2cimpl_destroy_func = dest_func; - j2cimpl_engineinfo_func = engineinfo_func; - all_functions_loaded = true; - } - } - } - } - - if ( !all_functions_loaded ) - { - //something went wrong with the DSO or function loading.. - //fall back onto our satefy impl creation function - -#if 0 - // precious verbose debugging, sadly we can't use our - // 'llinfos' stream etc. this early in the initialisation seq. - char errbuf[256]; - fprintf(stderr, "failed to load syms from DSO %s (%s)\n", - dso_name.c_str(), dso_path.c_str()); - apr_strerror(rv, errbuf, sizeof(errbuf)); - fprintf(stderr, "error: %d, %s\n", rv, errbuf); - apr_dso_error(j2cimpl_dso_handle, errbuf, sizeof(errbuf)); - fprintf(stderr, "dso-error: %d, %s\n", rv, errbuf); -#endif - - if ( j2cimpl_dso_handle ) - { - apr_dso_unload(j2cimpl_dso_handle); - j2cimpl_dso_handle = NULL; - } - - if ( j2cimpl_dso_memory_pool ) - { - apr_pool_destroy(j2cimpl_dso_memory_pool); - j2cimpl_dso_memory_pool = NULL; - } - } -} - -//static -void LLImageJ2C::closeDSO() -{ - if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle); - if (j2cimpl_dso_memory_pool) apr_pool_destroy(j2cimpl_dso_memory_pool); -} - //static std::string LLImageJ2C::getEngineInfo() { - if (!j2cimpl_engineinfo_func) - j2cimpl_engineinfo_func = fallbackEngineInfoLLImageJ2CImpl; - - return j2cimpl_engineinfo_func(); + return fallbackEngineInfoLLImageJ2CImpl(); } LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C), @@ -179,20 +57,7 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C), mReversible(FALSE), mAreaUsedForDataSizeCalcs(0) { - //We assume here that if we wanted to create via - //a dynamic library that the approriate open calls were made - //before any calls to this constructor. - - //Therefore, a NULL creation function pointer here means - //we either did not want to create using functions from the dynamic - //library or there were issues loading it, either way - //use our fall back - if ( !j2cimpl_create_func ) - { - j2cimpl_create_func = fallbackCreateLLImageJ2CImpl; - } - - mImpl = j2cimpl_create_func(); + mImpl = fallbackCreateLLImageJ2CImpl(); // Clear data size table for( S32 i = 0; i <= MAX_DISCARD_LEVEL; i++) @@ -214,22 +79,9 @@ LLImageJ2C::LLImageJ2C() : LLImageFormatted(IMG_CODEC_J2C), // virtual LLImageJ2C::~LLImageJ2C() { - //We assume here that if we wanted to destroy via - //a dynamic library that the approriate open calls were made - //before any calls to this destructor. - - //Therefore, a NULL creation function pointer here means - //we either did not want to destroy using functions from the dynamic - //library or there were issues loading it, either way - //use our fall back - if ( !j2cimpl_destroy_func ) - { - j2cimpl_destroy_func = fallbackDestroyLLImageJ2CImpl; - } - if ( mImpl ) { - j2cimpl_destroy_func(mImpl); + fallbackDestroyLLImageJ2CImpl(mImpl); } } diff --git a/indra/llimage/llimagej2c.h b/indra/llimage/llimagej2c.h index adbfb9cdb3..9191d7886a 100644 --- a/indra/llimage/llimagej2c.h +++ b/indra/llimage/llimagej2c.h @@ -72,8 +72,6 @@ public: static S32 calcHeaderSizeJ2C(); static S32 calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 rate = 0.f); - static void openDSO(); - static void closeDSO(); static std::string getEngineInfo(); // Image compression/decompression tester diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e9fb23d19e..c64184aa33 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1440,11 +1440,6 @@ if (WINDOWS) # In the meantime, if you have any ideas on how to easily maintain one list, either here or in viewer_manifest.py # and have the build deps get tracked *please* tell me about it. - if(LLKDU_LIBRARY) - # Configure a var for llkdu which may not exist for all builds. - set(LLKDU_DLL_SOURCE ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llkdu.dll) - endif(LLKDU_LIBRARY) - if(USE_GOOGLE_PERFTOOLS) # Configure a var for tcmalloc location, if used. # Note the need to specify multiple names explicitly. @@ -1461,7 +1456,6 @@ if (WINDOWS) #${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libtcmalloc_minimal.dll => None ... Skipping libtcmalloc_minimal.dll ${CMAKE_SOURCE_DIR}/../etc/message.xml ${CMAKE_SOURCE_DIR}/../scripts/messages/message_template.msg - ${LLKDU_DLL_SOURCE} ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/llcommon.dll ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libapr-1.dll ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/libaprutil-1.dll @@ -1638,7 +1632,6 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${LLAUDIO_LIBRARIES} ${LLCHARACTER_LIBRARIES} ${LLIMAGE_LIBRARIES} - ${LLIMAGEJ2COJ_LIBRARIES} ${LLINVENTORY_LIBRARIES} ${LLMESSAGE_LIBRARIES} ${LLPLUGIN_LIBRARIES} @@ -1674,6 +1667,17 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${GOOGLE_PERFTOOLS_LIBRARIES} ) +if (LLKDU_LIBRARY) + target_link_libraries(${VIEWER_BINARY_NAME} + ${LLKDU_STATIC_LIBRARIES} + ${KDU_LIBRARY} + ) +else (LLKDU_LIBRARY) + target_link_libraries(${VIEWER_BINARY_NAME} + ${LLIMAGEJ2COJ_LIBRARIES} + ) +endif (LLKDU_LIBRARY) + build_version(viewer) set(ARTWORK_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH diff --git a/install.xml b/install.xml index 5a9d704191..100ae6cc1d 100644 --- a/install.xml +++ b/install.xml @@ -830,23 +830,30 @@ darwin md5sum - ae18dd120807a46ac961b881a631ad94 + 3b40e7170dea82c1443e8d90cd44a13d url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/indra_private-2.1.1-darwin-20100820.tar.bz2 + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-4.2.1-darwin-20080926.tar.bz2 linux md5sum - b1f15bbabb68445e55ce23a2aeaca598 + a6d2f0995c25d7f53bd12b8ec0d6b462 url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/indra_private-2.1.1-linux-20100826.tar.bz2 + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-4.2.1-linux-20080930.tar.bz2 + + linux64 + + md5sum + f4e2e2b3440594527729a8c85119e508 + url + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-5.2.1-linux64-20080926.tar.bz2 windows md5sum - 0e2fe621ce99085eba00d86d9a3bc130 + 1b9f61140f8b599cdae5e00d21dbb177 url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/indra_private-2.1.1-windows-20100820.tar.bz2 + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-4.2.1-windows-20080926.tar.bz2 -- cgit v1.2.3 From 851f995287c0973368250b3dd8ed9a884b6a96b0 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Thu, 28 Oct 2010 08:48:26 -0700 Subject: ESC-109 Write single-thread asset stats collector for wearable. Code-complete with unit tests and foundation for other collectors. Interestingly, sim and viewer have two different ideas about asset type enumeration (compatible, one's just longer). Both are missing mesh though that's to be expected. --- indra/newview/CMakeLists.txt | 7 + indra/newview/llviewerassetstats.cpp | 277 ++++++++++++++++++++++++ indra/newview/llviewerassetstats.h | 143 ++++++++++++ indra/newview/tests/llviewerassetstats_test.cpp | 167 ++++++++++++++ 4 files changed, 594 insertions(+) create mode 100644 indra/newview/llviewerassetstats.cpp create mode 100644 indra/newview/llviewerassetstats.h create mode 100644 indra/newview/tests/llviewerassetstats_test.cpp diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 0c4d2aaca6..24ef079c7e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -476,6 +476,7 @@ set(viewer_SOURCE_FILES llvectorperfoptions.cpp llversioninfo.cpp llviewchildren.cpp + llviewerassetstats.cpp llviewerassetstorage.cpp llviewerassettype.cpp llviewerattachmenu.cpp @@ -1004,6 +1005,7 @@ set(viewer_HEADER_FILES llvectorperfoptions.h llversioninfo.h llviewchildren.h + llviewerassetstats.h llviewerassetstorage.h llviewerassettype.h llviewerattachmenu.h @@ -1930,6 +1932,11 @@ if (LL_TESTS) "${test_libs}" ) + LL_ADD_INTEGRATION_TEST(llviewerassetstats + llviewerassetstats.cpp + "${test_libs}" + ) + #ADD_VIEWER_BUILD_TEST(llmemoryview viewer) #ADD_VIEWER_BUILD_TEST(llagentaccess viewer) #ADD_VIEWER_BUILD_TEST(llworldmap viewer) diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp new file mode 100644 index 0000000000..f74b394d78 --- /dev/null +++ b/indra/newview/llviewerassetstats.cpp @@ -0,0 +1,277 @@ +/** + * @file llviewerassetstats.cpp + * @brief + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerassetstats.h" + +#include "stdtypes.h" + +/* + * References + * + * Project: + * + * + * Test Plan: + * + * + * Jiras: + * + * + * Unit Tests: + * + * + */ + + +// ------------------------------------------------------ +// Global data definitions +// ------------------------------------------------------ +LLViewerAssetStats * gViewerAssetStats = NULL; + + +// ------------------------------------------------------ +// Local declarations +// ------------------------------------------------------ +namespace +{ + +static LLViewerAssetStats::EViewerAssetCategories +asset_type_to_category(const LLViewerAssetType::EType at); + +} + +// ------------------------------------------------------ +// LLViewerAssetStats class definition +// ------------------------------------------------------ +LLViewerAssetStats::LLViewerAssetStats() +{ + reset(); +} + + +void +LLViewerAssetStats::reset() +{ + for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i) + { + mRequests[i].mEnqueued.reset(); + mRequests[i].mDequeued.reset(); + mRequests[i].mResponse.reset(); + } +} + +void +LLViewerAssetStats::recordGetEnqueued(LLViewerAssetType::EType at) +{ + const EViewerAssetCategories eac(asset_type_to_category(at)); + + ++mRequests[int(eac)].mEnqueued; +} + +void +LLViewerAssetStats::recordGetDequeued(LLViewerAssetType::EType at) +{ + const EViewerAssetCategories eac(asset_type_to_category(at)); + + ++mRequests[int(eac)].mDequeued; +} + +void +LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, F64 duration) +{ + const EViewerAssetCategories eac(asset_type_to_category(at)); + + mRequests[int(eac)].mResponse.record(duration); +} + +const LLSD +LLViewerAssetStats::asLLSD() const +{ + // Top-level tags + static const LLSD::String tags[EVACCount] = + { + LLSD::String("get_texture"), + LLSD::String("get_wearable"), + LLSD::String("get_sound"), + LLSD::String("get_gesture"), + LLSD::String("get_other") + }; + + // Sub-tags + static const LLSD::String enq_tag("enqueued"); + static const LLSD::String deq_tag("dequeued"); + static const LLSD::String rcnt_tag("resp_count"); + static const LLSD::String rmin_tag("resp_min"); + static const LLSD::String rmax_tag("resp_max"); + static const LLSD::String rmean_tag("resp_mean"); + + LLSD ret = LLSD::emptyMap(); + + for (int i = 0; i < EVACCount; ++i) + { + LLSD & slot = ret[tags[i]]; + slot = LLSD::emptyMap(); + slot[enq_tag] = LLSD(S32(mRequests[i].mEnqueued.getCount())); + slot[deq_tag] = LLSD(S32(mRequests[i].mDequeued.getCount())); + slot[rcnt_tag] = LLSD(S32(mRequests[i].mResponse.getCount())); + slot[rmin_tag] = LLSD(mRequests[i].mResponse.getMin()); + slot[rmax_tag] = LLSD(mRequests[i].mResponse.getMax()); + slot[rmean_tag] = LLSD(mRequests[i].mResponse.getMean()); + } + + return ret; +} + +// ------------------------------------------------------ +// Global free-function definitions (LLViewerAssetStatsFF namespace) +// ------------------------------------------------------ + +namespace LLViewerAssetStatsFF +{ + +void +record_enqueue(LLViewerAssetType::EType at) +{ + if (! gViewerAssetStats) + return; + + gViewerAssetStats->recordGetEnqueued(at); +} + +void +record_dequeue(LLViewerAssetType::EType at) +{ + if (! gViewerAssetStats) + return; + + gViewerAssetStats->recordGetDequeued(at); +} + +void +record_response(LLViewerAssetType::EType at, F64 duration) +{ + if (! gViewerAssetStats) + return; + + gViewerAssetStats->recordGetServiced(at, duration); +} + +} // namespace LLViewerAssetStatsFF + + +// ------------------------------------------------------ +// Local function definitions +// ------------------------------------------------------ + +namespace +{ + +LLViewerAssetStats::EViewerAssetCategories +asset_type_to_category(const LLViewerAssetType::EType at) +{ + // For statistical purposes, we divide GETs into several + // populations of asset fetches: + // - textures which are de-prioritized in the asset system + // - wearables (clothing, bodyparts) which directly affect + // user experiences when they log in + // - sounds + // - gestures + // - everything else. + // + llassert_always(26 == LLViewerAssetType::AT_COUNT); + + // Multiple asset definitions are floating around so this requires some + // maintenance and attention. + static const LLViewerAssetStats::EViewerAssetCategories asset_to_bin_map[LLViewerAssetType::AT_COUNT] = + { + LLViewerAssetStats::EVACTextureGet, // (0) AT_TEXTURE + LLViewerAssetStats::EVACSoundGet, // AT_SOUND + LLViewerAssetStats::EVACOtherGet, // AT_CALLINGCARD + LLViewerAssetStats::EVACOtherGet, // AT_LANDMARK + LLViewerAssetStats::EVACOtherGet, // AT_SCRIPT + LLViewerAssetStats::EVACWearableGet, // AT_CLOTHING + LLViewerAssetStats::EVACOtherGet, // AT_OBJECT + LLViewerAssetStats::EVACOtherGet, // AT_NOTECARD + LLViewerAssetStats::EVACOtherGet, // AT_CATEGORY + LLViewerAssetStats::EVACOtherGet, // AT_ROOT_CATEGORY + LLViewerAssetStats::EVACOtherGet, // (10) AT_LSL_TEXT + LLViewerAssetStats::EVACOtherGet, // AT_LSL_BYTECODE + LLViewerAssetStats::EVACOtherGet, // AT_TEXTURE_TGA + LLViewerAssetStats::EVACWearableGet, // AT_BODYPART + LLViewerAssetStats::EVACOtherGet, // AT_TRASH + LLViewerAssetStats::EVACOtherGet, // AT_SNAPSHOT_CATEGORY + LLViewerAssetStats::EVACOtherGet, // AT_LOST_AND_FOUND + LLViewerAssetStats::EVACSoundGet, // AT_SOUND_WAV + LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_TGA + LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_JPEG + LLViewerAssetStats::EVACGestureGet, // (20) AT_ANIMATION + LLViewerAssetStats::EVACGestureGet, // AT_GESTURE + LLViewerAssetStats::EVACOtherGet, // AT_SIMSTATE + LLViewerAssetStats::EVACOtherGet, // AT_FAVORITE + LLViewerAssetStats::EVACOtherGet, // AT_LINK + LLViewerAssetStats::EVACOtherGet, // AT_LINK_FOLDER +#if 0 + // When LLViewerAssetType::AT_COUNT == 49 + LLViewerAssetStats::EVACOtherGet, // AT_FOLDER_ENSEMBLE_START + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // (30) + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // (40) + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // AT_FOLDER_ENSEMBLE_END + LLViewerAssetStats::EVACOtherGet, // AT_CURRENT_OUTFIT + LLViewerAssetStats::EVACOtherGet, // AT_OUTFIT + LLViewerAssetStats::EVACOtherGet // AT_MY_OUTFITS +#endif + }; + + if (at < 0 || at >= LLViewerAssetType::AT_COUNT) + { + return LLViewerAssetStats::EVACOtherGet; + } + return asset_to_bin_map[at]; +} + +} // anonymous namespace diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h new file mode 100644 index 0000000000..b56fe008e3 --- /dev/null +++ b/indra/newview/llviewerassetstats.h @@ -0,0 +1,143 @@ +/** + * @file llviewerassetstats.h + * @brief Client-side collection of asset request statistics + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLVIEWERASSETSTATUS_H +#define LL_LLVIEWERASSETSTATUS_H + + +#include "linden_common.h" + +#include "llviewerassettype.h" +#include "llviewerassetstorage.h" +#include "llsimplestat.h" +#include "llsd.h" + +/** + * @class LLViewerAssetStats + * @brief Records events and performance of asset put/get operations. + * + * The asset system is a combination of common code and server- + * and viewer-overridden derivations. The common code is presented + * in here as the 'front-end' and deriviations (really the server) + * are presented as 'back-end'. The distinction isn't perfect as + * there are legacy asset transfer systems which mostly appear + * as front-end stats. + * + * Statistics collected are fairly basic: + * - Counts of enqueue and dequeue operations + * - Counts of duplicated request fetches + * - Min/Max/Mean of asset transfer operations + * + * While the stats collection interfaces appear to be fairly + * orthogonal across methods (GET, PUT) and asset types (texture, + * bodypart, etc.), the actual internal collection granularity + * varies greatly. GET's operations found in the cache are + * treated as a single group as are duplicate requests. Non- + * cached items are broken down into three groups: textures, + * wearables (bodyparts, clothing) and the rest. PUT operations + * are broken down into two categories: temporary assets and + * non-temp. Back-end operations do not distinguish asset types, + * only GET, PUT (temp) and PUT (non-temp). + * + * No coverage for Estate Assets or Inventory Item Assets which use + * some different interface conventions. It could be expanded to cover + * them. + * + * Access to results is by conversion to an LLSD with some standardized + * key names. The intent of this structure is to be emitted as + * standard syslog-based metrics formatting where it can be picked + * up by interested parties. + * + * For convenience, a set of free functions in namespace LLAssetStatsFF + * are provided which operate on various counters in a way that + * is highly-compatible with the simulator code. + */ +class LLViewerAssetStats +{ +public: + LLViewerAssetStats(); + // Default destructor and assignment operator are correct. + + enum EViewerAssetCategories + { + EVACTextureGet, //< Texture GETs + EVACWearableGet, //< Wearable GETs + EVACSoundGet, //< Sound GETs + EVACGestureGet, //< Gesture GETs + EVACOtherGet, //< Other GETs + + EVACCount // Must be last + }; + + void reset(); + + // Non-Cached GET Requests + void recordGetEnqueued(LLViewerAssetType::EType at); + void recordGetDequeued(LLViewerAssetType::EType at); + void recordGetServiced(LLViewerAssetType::EType at, F64 duration); + + // Report Generation + const LLSD asLLSD() const; + +protected: + + struct + { + LLSimpleStatCounter mEnqueued; + LLSimpleStatCounter mDequeued; + LLSimpleStatMMM<> mResponse; + } mRequests [EVACCount]; +}; + + +/** + * Expectation is that the simulator and other asset-handling + * code will create a single instance of the stats class and + * make it available here. The free functions examine this + * for non-zero and perform their functions conditionally. The + * instance methods themselves make no assumption about this. + */ +extern LLViewerAssetStats * gViewerAssetStats; + +namespace LLViewerAssetStatsFF +{ + +void record_enqueue(LLViewerAssetType::EType at); + +void record_dequeue(LLViewerAssetType::EType at); + +void record_response(LLViewerAssetType::EType at, F64 duration); + +} // namespace LLViewerAssetStatsFF + + +#endif // LL_LLVIEWERASSETSTATUS_H diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp new file mode 100644 index 0000000000..5c6cc1c8c8 --- /dev/null +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -0,0 +1,167 @@ +/** + * @file llviewerassetstats_tut.cpp + * @date 2010-10-28 + * @brief Test cases for some of newview/llviewerassetstats.cpp + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + * + * Copyright (c) 2010, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include +#include + +#include "lltut.h" +#include "../llviewerassetstats.h" + +static const char * all_keys[] = +{ + "get_other", + "get_texture", + "get_wearable", + "get_sound", + "get_gesture" +}; + +static const char * resp_keys[] = +{ + "get_other", + "get_texture", + "get_wearable", + "get_sound", + "get_gesture" +}; + +static const char * sub_keys[] = +{ + "dequeued", + "enqueued", + "resp_count", + "resp_max", + "resp_min", + "resp_mean" +}; + +namespace tut +{ + struct tst_viewerassetstats_index + {}; + typedef test_group tst_viewerassetstats_index_t; + typedef tst_viewerassetstats_index_t::object tst_viewerassetstats_index_object_t; + tut::tst_viewerassetstats_index_t tut_tst_viewerassetstats_index("tst_viewerassetstats_test"); + + // Testing free functions without global stats allocated + template<> template<> + void tst_viewerassetstats_index_object_t::test<1>() + { + // Check that helpers aren't bothered by missing global stats + ensure("Global gViewerAssetStats should be NULL", (NULL == gViewerAssetStats)); + + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE); + + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE); + + LLViewerAssetStatsFF::record_response(LLViewerAssetType::AT_GESTURE, 12.3); + } + + // Create a non-global instance and check the structure + template<> template<> + void tst_viewerassetstats_index_object_t::test<2>() + { + ensure("Global gViewerAssetStats should be NULL", (NULL == gViewerAssetStats)); + + LLViewerAssetStats * it = new LLViewerAssetStats(); + + ensure("Global gViewerAssetStats should still be NULL", (NULL == gViewerAssetStats)); + + LLSD sd = it->asLLSD(); + + delete it; + + // Check the structure of the LLSD + for (int i = 0; i < LL_ARRAY_SIZE(all_keys); ++i) + { + std::string line = llformat("Has '%s' key", all_keys[i]); + ensure(line, sd.has(all_keys[i])); + } + + for (int i = 0; i < LL_ARRAY_SIZE(resp_keys); ++i) + { + for (int j = 0; j < LL_ARRAY_SIZE(sub_keys); ++j) + { + std::string line = llformat("Key '%s' has '%s' key", resp_keys[i], sub_keys[j]); + ensure(line, sd[resp_keys[i]].has(sub_keys[j])); + } + } + } + + // Create a non-global instance and check some content + template<> template<> + void tst_viewerassetstats_index_object_t::test<3>() + { + LLViewerAssetStats * it = new LLViewerAssetStats(); + + LLSD sd = it->asLLSD(); + + delete it; + + // Check a few points on the tree for content + ensure("sd[get_texture][dequeued] is 0", (0 == sd["get_texture"]["dequeued"].asInteger())); + ensure("sd[get_sound][resp_min] is 0", (0.0 == sd["get_sound"]["resp_min"].asReal())); + } + + // Create a global instance and verify free functions do something useful + template<> template<> + void tst_viewerassetstats_index_object_t::test<4>() + { + gViewerAssetStats = new LLViewerAssetStats(); + + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE); + + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART); + + LLSD sd = gViewerAssetStats->asLLSD(); + + // Check a few points on the tree for content + ensure("sd[get_texture][enqueued] is 1", (1 == sd["get_texture"]["enqueued"].asInteger())); + ensure("sd[get_gesture][dequeued] is 0", (0 == sd["get_gesture"]["dequeued"].asInteger())); + + // Reset and check zeros... + gViewerAssetStats->reset(); + sd = gViewerAssetStats->asLLSD(); + + delete gViewerAssetStats; + gViewerAssetStats = NULL; + + ensure("sd[get_texture][enqueued] is reset", (0 == sd["get_texture"]["enqueued"].asInteger())); + ensure("sd[get_gesture][dequeued] is reset", (0 == sd["get_gesture"]["dequeued"].asInteger())); + } + +} -- cgit v1.2.3 From 1ed9d997a6c380f71f2da182c8083321e35b5034 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Fri, 29 Oct 2010 08:50:03 -0700 Subject: ESC-111 Texture interfaces Mainly expand the categories to include protocol and location/temp nature of texture asset. --- indra/newview/llviewerassetstats.cpp | 157 ++++++++++++++---------- indra/newview/llviewerassetstats.h | 27 ++-- indra/newview/tests/llviewerassetstats_test.cpp | 51 ++++---- 3 files changed, 134 insertions(+), 101 deletions(-) diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index f74b394d78..0852573bbd 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -65,7 +65,7 @@ namespace { static LLViewerAssetStats::EViewerAssetCategories -asset_type_to_category(const LLViewerAssetType::EType at); +asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp); } @@ -90,25 +90,25 @@ LLViewerAssetStats::reset() } void -LLViewerAssetStats::recordGetEnqueued(LLViewerAssetType::EType at) +LLViewerAssetStats::recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp) { - const EViewerAssetCategories eac(asset_type_to_category(at)); + const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); ++mRequests[int(eac)].mEnqueued; } void -LLViewerAssetStats::recordGetDequeued(LLViewerAssetType::EType at) +LLViewerAssetStats::recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp) { - const EViewerAssetCategories eac(asset_type_to_category(at)); + const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); ++mRequests[int(eac)].mDequeued; } void -LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, F64 duration) +LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration) { - const EViewerAssetCategories eac(asset_type_to_category(at)); + const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); mRequests[int(eac)].mResponse.record(duration); } @@ -119,10 +119,13 @@ LLViewerAssetStats::asLLSD() const // Top-level tags static const LLSD::String tags[EVACCount] = { - LLSD::String("get_texture"), - LLSD::String("get_wearable"), - LLSD::String("get_sound"), - LLSD::String("get_gesture"), + LLSD::String("get_texture_temp_http"), + LLSD::String("get_texture_temp_udp"), + LLSD::String("get_texture_non_temp_http"), + LLSD::String("get_texture_non_temp_udp"), + LLSD::String("get_wearable_udp"), + LLSD::String("get_sound_udp"), + LLSD::String("get_gesture_udp"), LLSD::String("get_other") }; @@ -159,30 +162,30 @@ namespace LLViewerAssetStatsFF { void -record_enqueue(LLViewerAssetType::EType at) +record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp) { if (! gViewerAssetStats) return; - gViewerAssetStats->recordGetEnqueued(at); + gViewerAssetStats->recordGetEnqueued(at, with_http, is_temp); } void -record_dequeue(LLViewerAssetType::EType at) +record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp) { if (! gViewerAssetStats) return; - gViewerAssetStats->recordGetDequeued(at); + gViewerAssetStats->recordGetDequeued(at, with_http, is_temp); } void -record_response(LLViewerAssetType::EType at, F64 duration) +record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration) { if (! gViewerAssetStats) return; - gViewerAssetStats->recordGetServiced(at, duration); + gViewerAssetStats->recordGetServiced(at, with_http, is_temp, duration); } } // namespace LLViewerAssetStatsFF @@ -196,7 +199,7 @@ namespace { LLViewerAssetStats::EViewerAssetCategories -asset_type_to_category(const LLViewerAssetType::EType at) +asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp) { // For statistical purposes, we divide GETs into several // populations of asset fetches: @@ -213,57 +216,57 @@ asset_type_to_category(const LLViewerAssetType::EType at) // maintenance and attention. static const LLViewerAssetStats::EViewerAssetCategories asset_to_bin_map[LLViewerAssetType::AT_COUNT] = { - LLViewerAssetStats::EVACTextureGet, // (0) AT_TEXTURE - LLViewerAssetStats::EVACSoundGet, // AT_SOUND - LLViewerAssetStats::EVACOtherGet, // AT_CALLINGCARD - LLViewerAssetStats::EVACOtherGet, // AT_LANDMARK - LLViewerAssetStats::EVACOtherGet, // AT_SCRIPT - LLViewerAssetStats::EVACWearableGet, // AT_CLOTHING - LLViewerAssetStats::EVACOtherGet, // AT_OBJECT - LLViewerAssetStats::EVACOtherGet, // AT_NOTECARD - LLViewerAssetStats::EVACOtherGet, // AT_CATEGORY - LLViewerAssetStats::EVACOtherGet, // AT_ROOT_CATEGORY - LLViewerAssetStats::EVACOtherGet, // (10) AT_LSL_TEXT - LLViewerAssetStats::EVACOtherGet, // AT_LSL_BYTECODE - LLViewerAssetStats::EVACOtherGet, // AT_TEXTURE_TGA - LLViewerAssetStats::EVACWearableGet, // AT_BODYPART - LLViewerAssetStats::EVACOtherGet, // AT_TRASH - LLViewerAssetStats::EVACOtherGet, // AT_SNAPSHOT_CATEGORY - LLViewerAssetStats::EVACOtherGet, // AT_LOST_AND_FOUND - LLViewerAssetStats::EVACSoundGet, // AT_SOUND_WAV - LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_TGA - LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_JPEG - LLViewerAssetStats::EVACGestureGet, // (20) AT_ANIMATION - LLViewerAssetStats::EVACGestureGet, // AT_GESTURE - LLViewerAssetStats::EVACOtherGet, // AT_SIMSTATE - LLViewerAssetStats::EVACOtherGet, // AT_FAVORITE - LLViewerAssetStats::EVACOtherGet, // AT_LINK - LLViewerAssetStats::EVACOtherGet, // AT_LINK_FOLDER + LLViewerAssetStats::EVACTextureTempHTTPGet, // (0) AT_TEXTURE + LLViewerAssetStats::EVACSoundUDPGet, // AT_SOUND + LLViewerAssetStats::EVACOtherGet, // AT_CALLINGCARD + LLViewerAssetStats::EVACOtherGet, // AT_LANDMARK + LLViewerAssetStats::EVACOtherGet, // AT_SCRIPT + LLViewerAssetStats::EVACWearableUDPGet, // AT_CLOTHING + LLViewerAssetStats::EVACOtherGet, // AT_OBJECT + LLViewerAssetStats::EVACOtherGet, // AT_NOTECARD + LLViewerAssetStats::EVACOtherGet, // AT_CATEGORY + LLViewerAssetStats::EVACOtherGet, // AT_ROOT_CATEGORY + LLViewerAssetStats::EVACOtherGet, // (10) AT_LSL_TEXT + LLViewerAssetStats::EVACOtherGet, // AT_LSL_BYTECODE + LLViewerAssetStats::EVACOtherGet, // AT_TEXTURE_TGA + LLViewerAssetStats::EVACWearableUDPGet, // AT_BODYPART + LLViewerAssetStats::EVACOtherGet, // AT_TRASH + LLViewerAssetStats::EVACOtherGet, // AT_SNAPSHOT_CATEGORY + LLViewerAssetStats::EVACOtherGet, // AT_LOST_AND_FOUND + LLViewerAssetStats::EVACSoundUDPGet, // AT_SOUND_WAV + LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_TGA + LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_JPEG + LLViewerAssetStats::EVACGestureUDPGet, // (20) AT_ANIMATION + LLViewerAssetStats::EVACGestureUDPGet, // AT_GESTURE + LLViewerAssetStats::EVACOtherGet, // AT_SIMSTATE + LLViewerAssetStats::EVACOtherGet, // AT_FAVORITE + LLViewerAssetStats::EVACOtherGet, // AT_LINK + LLViewerAssetStats::EVACOtherGet, // AT_LINK_FOLDER #if 0 // When LLViewerAssetType::AT_COUNT == 49 - LLViewerAssetStats::EVACOtherGet, // AT_FOLDER_ENSEMBLE_START - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // (30) - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // (40) - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // AT_FOLDER_ENSEMBLE_END - LLViewerAssetStats::EVACOtherGet, // AT_CURRENT_OUTFIT - LLViewerAssetStats::EVACOtherGet, // AT_OUTFIT - LLViewerAssetStats::EVACOtherGet // AT_MY_OUTFITS + LLViewerAssetStats::EVACOtherGet, // AT_FOLDER_ENSEMBLE_START + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // (30) + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // (40) + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // + LLViewerAssetStats::EVACOtherGet, // AT_FOLDER_ENSEMBLE_END + LLViewerAssetStats::EVACOtherGet, // AT_CURRENT_OUTFIT + LLViewerAssetStats::EVACOtherGet, // AT_OUTFIT + LLViewerAssetStats::EVACOtherGet // AT_MY_OUTFITS #endif }; @@ -271,7 +274,25 @@ asset_type_to_category(const LLViewerAssetType::EType at) { return LLViewerAssetStats::EVACOtherGet; } - return asset_to_bin_map[at]; + LLViewerAssetStats::EViewerAssetCategories ret(asset_to_bin_map[at]); + if (LLViewerAssetStats::EVACTextureTempHTTPGet == ret) + { + // Indexed with [is_temp][with_http] + static const LLViewerAssetStats::EViewerAssetCategories texture_bin_map[2][2] = + { + { + LLViewerAssetStats::EVACTextureNonTempUDPGet, + LLViewerAssetStats::EVACTextureNonTempHTTPGet, + }, + { + LLViewerAssetStats::EVACTextureTempUDPGet, + LLViewerAssetStats::EVACTextureTempHTTPGet, + } + }; + + ret = texture_bin_map[is_temp][with_http]; + } + return ret; } } // anonymous namespace diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index b56fe008e3..9d66a1e89b 100644 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -89,21 +89,24 @@ public: enum EViewerAssetCategories { - EVACTextureGet, //< Texture GETs - EVACWearableGet, //< Wearable GETs - EVACSoundGet, //< Sound GETs - EVACGestureGet, //< Gesture GETs - EVACOtherGet, //< Other GETs + EVACTextureTempHTTPGet, //< Texture GETs + EVACTextureTempUDPGet, //< Texture GETs + EVACTextureNonTempHTTPGet, //< Texture GETs + EVACTextureNonTempUDPGet, //< Texture GETs + EVACWearableUDPGet, //< Wearable GETs + EVACSoundUDPGet, //< Sound GETs + EVACGestureUDPGet, //< Gesture GETs + EVACOtherGet, //< Other GETs - EVACCount // Must be last + EVACCount // Must be last }; void reset(); // Non-Cached GET Requests - void recordGetEnqueued(LLViewerAssetType::EType at); - void recordGetDequeued(LLViewerAssetType::EType at); - void recordGetServiced(LLViewerAssetType::EType at, F64 duration); + void recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp); + void recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp); + void recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration); // Report Generation const LLSD asLLSD() const; @@ -131,11 +134,11 @@ extern LLViewerAssetStats * gViewerAssetStats; namespace LLViewerAssetStatsFF { -void record_enqueue(LLViewerAssetType::EType at); +void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp); -void record_dequeue(LLViewerAssetType::EType at); +void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp); -void record_response(LLViewerAssetType::EType at, F64 duration); +void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration); } // namespace LLViewerAssetStatsFF diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index 5c6cc1c8c8..50d348c7e3 100644 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -42,19 +42,25 @@ static const char * all_keys[] = { "get_other", - "get_texture", - "get_wearable", - "get_sound", - "get_gesture" + "get_texture_temp_http", + "get_texture_temp_udp", + "get_texture_non_temp_http", + "get_texture_non_temp_udp", + "get_wearable_udp", + "get_sound_udp", + "get_gesture_udp" }; static const char * resp_keys[] = { "get_other", - "get_texture", - "get_wearable", - "get_sound", - "get_gesture" + "get_texture_temp_http", + "get_texture_temp_udp", + "get_texture_non_temp_http", + "get_texture_non_temp_udp", + "get_wearable_udp", + "get_sound_udp", + "get_gesture_udp" }; static const char * sub_keys[] = @@ -82,11 +88,11 @@ namespace tut // Check that helpers aren't bothered by missing global stats ensure("Global gViewerAssetStats should be NULL", (NULL == gViewerAssetStats)); - LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_response(LLViewerAssetType::AT_GESTURE, 12.3); + LLViewerAssetStatsFF::record_response(LLViewerAssetType::AT_GESTURE, false, false, 12.3); } // Create a non-global instance and check the structure @@ -131,8 +137,8 @@ namespace tut delete it; // Check a few points on the tree for content - ensure("sd[get_texture][dequeued] is 0", (0 == sd["get_texture"]["dequeued"].asInteger())); - ensure("sd[get_sound][resp_min] is 0", (0.0 == sd["get_sound"]["resp_min"].asReal())); + ensure("sd[get_texture_temp_http][dequeued] is 0", (0 == sd["get_texture_temp_http"]["dequeued"].asInteger())); + ensure("sd[get_sound_udp][resp_min] is 0", (0.0 == sd["get_sound_udp"]["resp_min"].asReal())); } // Create a global instance and verify free functions do something useful @@ -141,17 +147,20 @@ namespace tut { gViewerAssetStats = new LLViewerAssetStats(); - LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE); - LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART); - LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, false, false); LLSD sd = gViewerAssetStats->asLLSD(); // Check a few points on the tree for content - ensure("sd[get_texture][enqueued] is 1", (1 == sd["get_texture"]["enqueued"].asInteger())); - ensure("sd[get_gesture][dequeued] is 0", (0 == sd["get_gesture"]["dequeued"].asInteger())); + ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); + ensure("sd[get_texture_temp_udp][enqueued] is 0", (0 == sd["get_texture_temp_udp"]["enqueued"].asInteger())); + ensure("sd[get_texture_non_temp_http][enqueued] is 0", (0 == sd["get_texture_non_temp_http"]["enqueued"].asInteger())); + ensure("sd[get_texture_temp_http][enqueued] is 0", (0 == sd["get_texture_temp_http"]["enqueued"].asInteger())); + ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); // Reset and check zeros... gViewerAssetStats->reset(); @@ -160,8 +169,8 @@ namespace tut delete gViewerAssetStats; gViewerAssetStats = NULL; - ensure("sd[get_texture][enqueued] is reset", (0 == sd["get_texture"]["enqueued"].asInteger())); - ensure("sd[get_gesture][dequeued] is reset", (0 == sd["get_gesture"]["dequeued"].asInteger())); + ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); + ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); } } -- cgit v1.2.3 From 68d27467610610f8067a74fdecdfad595e6662b4 Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 5 Nov 2010 16:53:10 -0700 Subject: EXP-417 FIX Tab keys in embedded Web form moves focus out of Web page back to container XUI Reviewed by Richard. --- indra/newview/llmediactrl.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index e84c9152b1..5e27004ed8 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -432,13 +432,15 @@ BOOL LLMediaCtrl::postBuild () // BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) { - if (LLPanel::handleKeyHere(key, mask)) return TRUE; BOOL result = FALSE; if (mMediaSource) { result = mMediaSource->handleKeyHere(key, mask); } + + if ( ! result ) + result = LLPanel::handleKeyHere(key, mask); return result; } @@ -458,7 +460,6 @@ void LLMediaCtrl::handleVisibilityChange ( BOOL new_visibility ) // BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) { - if (LLPanel::handleUnicodeCharHere(uni_char)) return TRUE; BOOL result = FALSE; if (mMediaSource) @@ -466,6 +467,9 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) result = mMediaSource->handleUnicodeCharHere(uni_char); } + if ( ! result ) + result = LLPanel::handleUnicodeCharHere(uni_char); + return result; } -- cgit v1.2.3 From ce613ce398c3430beab13be6a8016e4c8f5dcab1 Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 5 Nov 2010 17:06:21 -0700 Subject: EXP-378 FIX Disable SSL cert errors in LLQtWebkit for testing purposes (Monroe's code - I made a patch and copied it over from viewer-skylight branch) --- indra/llplugin/llpluginclassmedia.cpp | 7 +++++++ indra/llplugin/llpluginclassmedia.h | 1 + indra/media_plugins/webkit/media_plugin_webkit.cpp | 8 ++++++++ indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llviewermedia.cpp | 5 +++++ 5 files changed, 32 insertions(+) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 69ed0fb09c..446df646fc 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -1192,6 +1192,13 @@ void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid) sendMessage(message); } +void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors"); + message.setValueBoolean("ignore", ignore); + sendMessage(message); +} + void LLPluginClassMedia::crashPlugin() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 9cb67fe909..938e5c1bf6 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -198,6 +198,7 @@ public: void setBrowserUserAgent(const std::string& user_agent); void proxyWindowOpened(const std::string &target, const std::string &uuid); void proxyWindowClosed(const std::string &uuid); + void ignore_ssl_cert_errors(bool ignore); // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE std::string getNavigateURI() const { return mNavigateURI; }; diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index bd1a44a930..466b4732b1 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -1182,6 +1182,14 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) mUserAgent = message_in.getValue("user_agent"); LLQtWebKit::getInstance()->setBrowserAgentId( mUserAgent ); } + else if(message_name == "ignore_ssl_cert_errors") + { +#if LLQTWEBKIT_API_VERSION >= 3 + LLQtWebKit::getInstance()->setIgnoreSSLCertErrors( message_in.getValueBoolean("ignore") ); +#else + llwarns << "Ignoring ignore_ssl_cert_errors message (llqtwebkit version is too old)." << llendl; +#endif + } else if(message_name == "init_history") { // Initialize browser history diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 3f23fee865..96aadba7cc 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -663,6 +663,17 @@ Value http://www.secondlife.com + BrowserIgnoreSSLCertErrors + + Comment + FOR TESTING ONLY: Tell the built-in web browser to ignore SSL cert errors. + Persist + 1 + Type + Boolean + Value + 0 + BlockAvatarAppearanceMessages Comment diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 48ab122edf..72aeab86d9 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1753,6 +1753,11 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) media_source->focus(mHasFocus); media_source->setBackgroundColor(mBackgroundColor); + if(gSavedSettings.getBOOL("BrowserIgnoreSSLCertErrors")) + { + media_source->ignore_ssl_cert_errors(true); + } + media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort")); if(mClearCache) -- cgit v1.2.3 From e3956440321764209100b28e7f6fcb883400c254 Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 9 Nov 2010 17:10:34 -0800 Subject: Trivial change to force a build in Team City. --- indra/media_plugins/webkit/media_plugin_webkit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 466b4732b1..15c107cbe1 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -341,7 +341,7 @@ private: url << std::setfill('0') << std::setw(2) << std::hex << int(mBackgroundB * 255.0f); url << "%22%3E%3C/body%3E%3C/html%3E"; - lldebugs << "data url is: " << url.str() << llendl; + //lldebugs << "data url is: " << url.str() << llendl; LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, url.str() ); // LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" ); -- cgit v1.2.3 From fd2d4dc1b16430edd367a8b0f4162238bbb7e22c Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Wed, 10 Nov 2010 08:44:53 -0800 Subject: ESC-110 ESC-111 Cleanup passes on the two threaded collectors with better comments and more complete unit tests. --- indra/newview/llviewerassetstats.cpp | 172 +++++++++++--- indra/newview/llviewerassetstats.h | 152 ++++++++---- indra/newview/tests/llviewerassetstats_test.cpp | 303 ++++++++++++++++++++++-- 3 files changed, 533 insertions(+), 94 deletions(-) diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index 0852573bbd..a6c4685bf1 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -47,7 +47,7 @@ * * * Unit Tests: - * + * indra/newview/tests/llviewerassetstats_test.cpp * */ @@ -55,7 +55,8 @@ // ------------------------------------------------------ // Global data definitions // ------------------------------------------------------ -LLViewerAssetStats * gViewerAssetStats = NULL; +LLViewerAssetStats * gViewerAssetStatsMain(0); +LLViewerAssetStats * gViewerAssetStatsThread1(0); // ------------------------------------------------------ @@ -69,6 +70,21 @@ asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool i } +// ------------------------------------------------------ +// LLViewerAssetStats::PerRegionStats struct definition +// ------------------------------------------------------ +void +LLViewerAssetStats::PerRegionStats::reset() +{ + for (int i(0); i < LL_ARRAY_SIZE(mRequests); ++i) + { + mRequests[i].mEnqueued.reset(); + mRequests[i].mDequeued.reset(); + mRequests[i].mResponse.reset(); + } +} + + // ------------------------------------------------------ // LLViewerAssetStats class definition // ------------------------------------------------------ @@ -81,20 +97,55 @@ LLViewerAssetStats::LLViewerAssetStats() void LLViewerAssetStats::reset() { - for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i) + // Empty the map of all region stats + mRegionStats.clear(); + + // If we have a current stats, reset it, otherwise, as at construction, + // create a new one. + if (mCurRegionStats) { - mRequests[i].mEnqueued.reset(); - mRequests[i].mDequeued.reset(); - mRequests[i].mResponse.reset(); + mCurRegionStats->reset(); } + else + { + mCurRegionStats = new PerRegionStats(mRegionID); + } + + // And add reference to map + mRegionStats[mRegionID] = mCurRegionStats; } + +void +LLViewerAssetStats::setRegionID(const LLUUID & region_id) +{ + if (region_id == mRegionID) + { + // Already active, ignore. + return; + } + + PerRegionContainer::iterator new_stats = mRegionStats.find(region_id); + if (mRegionStats.end() == new_stats) + { + // Haven't seen this region_id before, create a new block make it current. + mCurRegionStats = new PerRegionStats(region_id); + mRegionStats[region_id] = mCurRegionStats; + } + else + { + mCurRegionStats = new_stats->second; + } + mRegionID = region_id; +} + + void LLViewerAssetStats::recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp) { const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); - ++mRequests[int(eac)].mEnqueued; + ++(mCurRegionStats->mRequests[int(eac)].mEnqueued); } void @@ -102,7 +153,7 @@ LLViewerAssetStats::recordGetDequeued(LLViewerAssetType::EType at, bool with_htt { const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); - ++mRequests[int(eac)].mDequeued; + ++(mCurRegionStats->mRequests[int(eac)].mDequeued); } void @@ -110,7 +161,7 @@ LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, bool with_htt { const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); - mRequests[int(eac)].mResponse.record(duration); + mCurRegionStats->mRequests[int(eac)].mResponse.record(duration); } const LLSD @@ -139,16 +190,33 @@ LLViewerAssetStats::asLLSD() const LLSD ret = LLSD::emptyMap(); - for (int i = 0; i < EVACCount; ++i) + for (PerRegionContainer::const_iterator it = mRegionStats.begin(); + mRegionStats.end() != it; + ++it) { - LLSD & slot = ret[tags[i]]; - slot = LLSD::emptyMap(); - slot[enq_tag] = LLSD(S32(mRequests[i].mEnqueued.getCount())); - slot[deq_tag] = LLSD(S32(mRequests[i].mDequeued.getCount())); - slot[rcnt_tag] = LLSD(S32(mRequests[i].mResponse.getCount())); - slot[rmin_tag] = LLSD(mRequests[i].mResponse.getMin()); - slot[rmax_tag] = LLSD(mRequests[i].mResponse.getMax()); - slot[rmean_tag] = LLSD(mRequests[i].mResponse.getMean()); + if (it->first.isNull()) + { + // Never emit NULL UUID in results. + continue; + } + + const PerRegionStats & stats = *it->second; + + LLSD reg_stat = LLSD::emptyMap(); + + for (int i = 0; i < EVACCount; ++i) + { + LLSD & slot = reg_stat[tags[i]]; + slot = LLSD::emptyMap(); + slot[enq_tag] = LLSD(S32(stats.mRequests[i].mEnqueued.getCount())); + slot[deq_tag] = LLSD(S32(stats.mRequests[i].mDequeued.getCount())); + slot[rcnt_tag] = LLSD(S32(stats.mRequests[i].mResponse.getCount())); + slot[rmin_tag] = LLSD(stats.mRequests[i].mResponse.getMin()); + slot[rmax_tag] = LLSD(stats.mRequests[i].mResponse.getMax()); + slot[rmean_tag] = LLSD(stats.mRequests[i].mResponse.getMean()); + } + + ret[it->first.asString()] = reg_stat; } return ret; @@ -161,31 +229,81 @@ LLViewerAssetStats::asLLSD() const namespace LLViewerAssetStatsFF { +// Target thread is elaborated in the function name. This could +// have been something 'templatey' like specializations iterated +// over a set of constants but with so few, this is clearer I think. + +void +set_region_main(const LLUUID & region_id) +{ + if (! gViewerAssetStatsMain) + return; + + gViewerAssetStatsMain->setRegionID(region_id); +} + +void +record_enqueue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp) +{ + if (! gViewerAssetStatsMain) + return; + + gViewerAssetStatsMain->recordGetEnqueued(at, with_http, is_temp); +} + +void +record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp) +{ + if (! gViewerAssetStatsMain) + return; + + gViewerAssetStatsMain->recordGetDequeued(at, with_http, is_temp); +} + +void +record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration) +{ + if (! gViewerAssetStatsMain) + return; + + gViewerAssetStatsMain->recordGetServiced(at, with_http, is_temp, duration); +} + + +void +set_region_thread1(const LLUUID & region_id) +{ + if (! gViewerAssetStatsThread1) + return; + + gViewerAssetStatsThread1->setRegionID(region_id); +} + void -record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp) +record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp) { - if (! gViewerAssetStats) + if (! gViewerAssetStatsThread1) return; - gViewerAssetStats->recordGetEnqueued(at, with_http, is_temp); + gViewerAssetStatsThread1->recordGetEnqueued(at, with_http, is_temp); } void -record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp) +record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp) { - if (! gViewerAssetStats) + if (! gViewerAssetStatsThread1) return; - gViewerAssetStats->recordGetDequeued(at, with_http, is_temp); + gViewerAssetStatsThread1->recordGetDequeued(at, with_http, is_temp); } void -record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration) +record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration) { - if (! gViewerAssetStats) + if (! gViewerAssetStatsThread1) return; - gViewerAssetStats->recordGetServiced(at, with_http, is_temp, duration); + gViewerAssetStatsThread1->recordGetServiced(at, with_http, is_temp, duration); } } // namespace LLViewerAssetStatsFF diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index 9d66a1e89b..b8356a5ff5 100644 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -36,6 +36,8 @@ #include "linden_common.h" +#include "llpointer.h" +#include "llrefcount.h" #include "llviewerassettype.h" #include "llviewerassetstorage.h" #include "llsimplestat.h" @@ -43,50 +45,42 @@ /** * @class LLViewerAssetStats - * @brief Records events and performance of asset put/get operations. + * @brief Records performance aspects of asset access operations. * - * The asset system is a combination of common code and server- - * and viewer-overridden derivations. The common code is presented - * in here as the 'front-end' and deriviations (really the server) - * are presented as 'back-end'. The distinction isn't perfect as - * there are legacy asset transfer systems which mostly appear - * as front-end stats. + * This facility is derived from a very similar simulator-based + * one, LLSimAssetStats. It's function is to count asset access + * operations and characterize response times. Collected data + * are binned in several dimensions: + * + * - Asset types collapsed into a few aggregated categories + * - By simulator UUID + * - By transport mechanism (HTTP vs MessageSystem) + * - By persistence (temp vs non-temp) + * + * Statistics collected are fairly basic at this point: * - * Statistics collected are fairly basic: * - Counts of enqueue and dequeue operations - * - Counts of duplicated request fetches * - Min/Max/Mean of asset transfer operations * - * While the stats collection interfaces appear to be fairly - * orthogonal across methods (GET, PUT) and asset types (texture, - * bodypart, etc.), the actual internal collection granularity - * varies greatly. GET's operations found in the cache are - * treated as a single group as are duplicate requests. Non- - * cached items are broken down into three groups: textures, - * wearables (bodyparts, clothing) and the rest. PUT operations - * are broken down into two categories: temporary assets and - * non-temp. Back-end operations do not distinguish asset types, - * only GET, PUT (temp) and PUT (non-temp). - * - * No coverage for Estate Assets or Inventory Item Assets which use - * some different interface conventions. It could be expanded to cover - * them. + * This collector differs from the simulator-based on in a + * number of ways: + * + * - The front-end/back-end distinction doesn't exist in viewer + * code + * - Multiple threads must be safely accomodated in the viewer * * Access to results is by conversion to an LLSD with some standardized - * key names. The intent of this structure is to be emitted as + * key names. The intent of this structure is that it be emitted as * standard syslog-based metrics formatting where it can be picked * up by interested parties. * - * For convenience, a set of free functions in namespace LLAssetStatsFF - * are provided which operate on various counters in a way that - * is highly-compatible with the simulator code. + * For convenience, a set of free functions in namespace + * LLViewerAssetStatsFF is provided for conditional test-and-call + * operations. */ class LLViewerAssetStats { public: - LLViewerAssetStats(); - // Default destructor and assignment operator are correct. - enum EViewerAssetCategories { EVACTextureTempHTTPGet, //< Texture GETs @@ -100,45 +94,109 @@ public: EVACCount // Must be last }; - + + /** + * Collected data for a single region visited by the avatar. + */ + class PerRegionStats : public LLRefCount + { + public: + PerRegionStats(const LLUUID & region_id) + : LLRefCount(), + mRegionID(region_id) + { + reset(); + } + + void reset(); + + public: + LLUUID mRegionID; + struct + { + LLSimpleStatCounter mEnqueued; + LLSimpleStatCounter mDequeued; + LLSimpleStatMMM<> mResponse; + } mRequests [EVACCount]; + }; + +public: + LLViewerAssetStats(); + // Default destructor is correct. + LLViewerAssetStats & operator=(const LLViewerAssetStats &); // Not defined + + // Clear all metrics data. This leaves the currently-active region + // in place but with zero'd data for all metrics. All other regions + // are removed from the collection map. void reset(); + // Set hidden region argument and establish context for subsequent + // collection calls. + void setRegionID(const LLUUID & region_id); + // Non-Cached GET Requests void recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp); void recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp); void recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration); - // Report Generation + // Retrieve current metrics for all visited regions. const LLSD asLLSD() const; protected: + typedef std::map > PerRegionContainer; - struct - { - LLSimpleStatCounter mEnqueued; - LLSimpleStatCounter mDequeued; - LLSimpleStatMMM<> mResponse; - } mRequests [EVACCount]; + // Region of the currently-active region. Always valid but may + // be a NULL UUID after construction or when explicitly set. Unchanged + // by a reset() call. + LLUUID mRegionID; + + // Pointer to metrics collection for currently-active region. Always + // valid and unchanged after reset() though contents will be changed. + // Always points to a collection contained in mRegionStats. + LLPointer mCurRegionStats; + + // Metrics data for all regions during one collection cycle + PerRegionContainer mRegionStats; }; /** - * Expectation is that the simulator and other asset-handling - * code will create a single instance of the stats class and - * make it available here. The free functions examine this - * for non-zero and perform their functions conditionally. The - * instance methods themselves make no assumption about this. + * Global stats collectors one for each independent thread where + * assets and other statistics are gathered. The globals are + * expected to be created at startup time and then picked up by + * their respective threads afterwards. A set of free functions + * are provided to access methods behind the globals while both + * minimally disrupting visual flow and supplying a description + * of intent. + * + * Expected thread assignments: + * + * - Main: main() program execution thread + * - Thread1: TextureFetch worker thread */ -extern LLViewerAssetStats * gViewerAssetStats; +extern LLViewerAssetStats * gViewerAssetStatsMain; + +extern LLViewerAssetStats * gViewerAssetStatsThread1; namespace LLViewerAssetStatsFF { -void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp); +void set_region_main(const LLUUID & region_id); + +void record_enqueue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp); + +void record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp); + +void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration); + + +void set_region_thread1(const LLUUID & region_id); + +void record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp); -void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp); +void record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp); -void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration); +void record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration); } // namespace LLViewerAssetStatsFF diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index 50d348c7e3..affe16c177 100644 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -38,6 +38,7 @@ #include "lltut.h" #include "../llviewerassetstats.h" +#include "lluuid.h" static const char * all_keys[] = { @@ -73,6 +74,27 @@ static const char * sub_keys[] = "resp_mean" }; +static const LLUUID region1("4e2d81a3-6263-6ffe-ad5c-8ce04bee07e8"); +static const LLUUID region2("68762cc8-b68b-4e45-854b-e830734f2d4a"); + +static bool +is_empty_map(const LLSD & sd) +{ + return sd.isMap() && 0 == sd.size(); +} + +static bool +is_single_key_map(const LLSD & sd, const std::string & key) +{ + return sd.isMap() && 1 == sd.size() && sd.has(key); +} + +static bool +is_double_key_map(const LLSD & sd, const std::string & key1, const std::string & key2) +{ + return sd.isMap() && 2 == sd.size() && sd.has(key1) && sd.has(key2); +} + namespace tut { struct tst_viewerassetstats_index @@ -86,29 +108,40 @@ namespace tut void tst_viewerassetstats_index_object_t::test<1>() { // Check that helpers aren't bothered by missing global stats - ensure("Global gViewerAssetStats should be NULL", (NULL == gViewerAssetStats)); + ensure("Global gViewerAssetStatsMain should be NULL", (NULL == gViewerAssetStatsMain)); - LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_response(LLViewerAssetType::AT_GESTURE, false, false, 12.3); + LLViewerAssetStatsFF::record_response_main(LLViewerAssetType::AT_GESTURE, false, false, 12.3); } // Create a non-global instance and check the structure template<> template<> void tst_viewerassetstats_index_object_t::test<2>() { - ensure("Global gViewerAssetStats should be NULL", (NULL == gViewerAssetStats)); + ensure("Global gViewerAssetStatsMain should be NULL", (NULL == gViewerAssetStatsMain)); LLViewerAssetStats * it = new LLViewerAssetStats(); - ensure("Global gViewerAssetStats should still be NULL", (NULL == gViewerAssetStats)); - - LLSD sd = it->asLLSD(); - - delete it; + ensure("Global gViewerAssetStatsMain should still be NULL", (NULL == gViewerAssetStatsMain)); + LLSD sd_full = it->asLLSD(); + + // Default (NULL) region ID doesn't produce LLSD results so should + // get an empty map back from output + ensure("Null LLSD initially", is_empty_map(sd_full)); + + // Once the region is set, we will get a response even with no data collection + it->setRegionID(region1); + sd_full = it->asLLSD(); + ensure("Correct single-key LLSD map", is_single_key_map(sd_full, region1.asString())); + + LLSD sd = sd_full[region1.asString()]; + + delete it; + // Check the structure of the LLSD for (int i = 0; i < LL_ARRAY_SIZE(all_keys); ++i) { @@ -131,8 +164,11 @@ namespace tut void tst_viewerassetstats_index_object_t::test<3>() { LLViewerAssetStats * it = new LLViewerAssetStats(); + it->setRegionID(region1); LLSD sd = it->asLLSD(); + ensure("Correct single-key LLSD map", is_single_key_map(sd, region1.asString())); + sd = sd[region1.asString()]; delete it; @@ -145,15 +181,57 @@ namespace tut template<> template<> void tst_viewerassetstats_index_object_t::test<4>() { - gViewerAssetStats = new LLViewerAssetStats(); + gViewerAssetStatsMain = new LLViewerAssetStats(); + LLViewerAssetStatsFF::set_region_main(region1); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + + LLSD sd = gViewerAssetStatsMain->asLLSD(); + ensure("Correct single-key LLSD map", is_single_key_map(sd, region1.asString())); + sd = sd[region1.asString()]; + + // Check a few points on the tree for content + ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); + ensure("sd[get_texture_temp_udp][enqueued] is 0", (0 == sd["get_texture_temp_udp"]["enqueued"].asInteger())); + ensure("sd[get_texture_non_temp_http][enqueued] is 0", (0 == sd["get_texture_non_temp_http"]["enqueued"].asInteger())); + ensure("sd[get_texture_temp_http][enqueued] is 0", (0 == sd["get_texture_temp_http"]["enqueued"].asInteger())); + ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); + + // Reset and check zeros... + // Reset leaves current region in place + gViewerAssetStatsMain->reset(); + sd = gViewerAssetStatsMain->asLLSD()[region1.asString()]; + + delete gViewerAssetStatsMain; + gViewerAssetStatsMain = NULL; + + ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); + ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); + } + + // Create two global instances and verify no interactions + template<> template<> + void tst_viewerassetstats_index_object_t::test<5>() + { + gViewerAssetStatsThread1 = new LLViewerAssetStats(); + gViewerAssetStatsMain = new LLViewerAssetStats(); + LLViewerAssetStatsFF::set_region_main(region1); - LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); - LLSD sd = gViewerAssetStats->asLLSD(); + LLSD sd = gViewerAssetStatsThread1->asLLSD(); + ensure("Other collector is empty", is_empty_map(sd)); + sd = gViewerAssetStatsMain->asLLSD(); + ensure("Correct single-key LLSD map", is_single_key_map(sd, region1.asString())); + sd = sd[region1.asString()]; // Check a few points on the tree for content ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); @@ -163,11 +241,196 @@ namespace tut ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); // Reset and check zeros... - gViewerAssetStats->reset(); - sd = gViewerAssetStats->asLLSD(); + // Reset leaves current region in place + gViewerAssetStatsMain->reset(); + sd = gViewerAssetStatsMain->asLLSD()[region1.asString()]; + + delete gViewerAssetStatsMain; + gViewerAssetStatsMain = NULL; + delete gViewerAssetStatsThread1; + gViewerAssetStatsThread1 = NULL; + + ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); + ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); + } + + // Check multiple region collection + template<> template<> + void tst_viewerassetstats_index_object_t::test<6>() + { + gViewerAssetStatsMain = new LLViewerAssetStats(); + + LLViewerAssetStatsFF::set_region_main(region1); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + + LLViewerAssetStatsFF::set_region_main(region2); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + + LLSD sd = gViewerAssetStatsMain->asLLSD(); + + ensure("Correct double-key LLSD map", is_double_key_map(sd, region1.asString(), region2.asString())); + LLSD sd1 = sd[region1.asString()]; + LLSD sd2 = sd[region2.asString()]; + + // Check a few points on the tree for content + ensure("sd1[get_texture_non_temp_udp][enqueued] is 1", (1 == sd1["get_texture_non_temp_udp"]["enqueued"].asInteger())); + ensure("sd1[get_texture_temp_udp][enqueued] is 0", (0 == sd1["get_texture_temp_udp"]["enqueued"].asInteger())); + ensure("sd1[get_texture_non_temp_http][enqueued] is 0", (0 == sd1["get_texture_non_temp_http"]["enqueued"].asInteger())); + ensure("sd1[get_texture_temp_http][enqueued] is 0", (0 == sd1["get_texture_temp_http"]["enqueued"].asInteger())); + ensure("sd1[get_gesture_udp][dequeued] is 0", (0 == sd1["get_gesture_udp"]["dequeued"].asInteger())); + + // Check a few points on the tree for content + ensure("sd2[get_gesture_udp][enqueued] is 4", (4 == sd2["get_gesture_udp"]["enqueued"].asInteger())); + ensure("sd2[get_gesture_udp][dequeued] is 0", (0 == sd2["get_gesture_udp"]["dequeued"].asInteger())); + ensure("sd2[get_texture_non_temp_udp][enqueued] is 0", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger())); + + // Reset and check zeros... + // Reset leaves current region in place + gViewerAssetStatsMain->reset(); + sd = gViewerAssetStatsMain->asLLSD(); + ensure("Correct single-key LLSD map", is_single_key_map(sd, region2.asString())); + sd2 = sd[region2.asString()]; + + delete gViewerAssetStatsMain; + gViewerAssetStatsMain = NULL; + + ensure("sd2[get_texture_non_temp_udp][enqueued] is reset", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger())); + ensure("sd2[get_gesture_udp][enqueued] is reset", (0 == sd2["get_gesture_udp"]["enqueued"].asInteger())); + } + + // Check multiple region collection jumping back-and-forth between regions + template<> template<> + void tst_viewerassetstats_index_object_t::test<7>() + { + gViewerAssetStatsMain = new LLViewerAssetStats(); + + LLViewerAssetStatsFF::set_region_main(region1); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + + LLViewerAssetStatsFF::set_region_main(region2); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + + LLViewerAssetStatsFF::set_region_main(region1); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, true, true); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, true, true); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + + LLViewerAssetStatsFF::set_region_main(region2); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + + LLSD sd = gViewerAssetStatsMain->asLLSD(); + + ensure("Correct double-key LLSD map", is_double_key_map(sd, region1.asString(), region2.asString())); + LLSD sd1 = sd[region1.asString()]; + LLSD sd2 = sd[region2.asString()]; + + // Check a few points on the tree for content + ensure("sd1[get_texture_non_temp_udp][enqueued] is 1", (1 == sd1["get_texture_non_temp_udp"]["enqueued"].asInteger())); + ensure("sd1[get_texture_temp_udp][enqueued] is 0", (0 == sd1["get_texture_temp_udp"]["enqueued"].asInteger())); + ensure("sd1[get_texture_non_temp_http][enqueued] is 0", (0 == sd1["get_texture_non_temp_http"]["enqueued"].asInteger())); + ensure("sd1[get_texture_temp_http][enqueued] is 1", (1 == sd1["get_texture_temp_http"]["enqueued"].asInteger())); + ensure("sd1[get_gesture_udp][dequeued] is 0", (0 == sd1["get_gesture_udp"]["dequeued"].asInteger())); + + // Check a few points on the tree for content + ensure("sd2[get_gesture_udp][enqueued] is 8", (8 == sd2["get_gesture_udp"]["enqueued"].asInteger())); + ensure("sd2[get_gesture_udp][dequeued] is 0", (0 == sd2["get_gesture_udp"]["dequeued"].asInteger())); + ensure("sd2[get_texture_non_temp_udp][enqueued] is 0", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger())); + + // Reset and check zeros... + // Reset leaves current region in place + gViewerAssetStatsMain->reset(); + sd = gViewerAssetStatsMain->asLLSD(); + ensure("Correct single-key LLSD map", is_single_key_map(sd, region2.asString())); + sd2 = sd[region2.asString()]; + + delete gViewerAssetStatsMain; + gViewerAssetStatsMain = NULL; + + ensure("sd2[get_texture_non_temp_udp][enqueued] is reset", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger())); + ensure("sd2[get_gesture_udp][enqueued] is reset", (0 == sd2["get_gesture_udp"]["enqueued"].asInteger())); + } + + // Non-texture assets ignore transport and persistence flags + template<> template<> + void tst_viewerassetstats_index_object_t::test<8>() + { + gViewerAssetStatsThread1 = new LLViewerAssetStats(); + gViewerAssetStatsMain = new LLViewerAssetStats(); + LLViewerAssetStatsFF::set_region_main(region1); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, true); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, true); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, true, false); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, true, false); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, true, true); + LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, true, true); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, false, false); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, false, true); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, false); + + LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + LLSD sd = gViewerAssetStatsThread1->asLLSD(); + ensure("Other collector is empty", is_empty_map(sd)); + sd = gViewerAssetStatsMain->asLLSD(); + ensure("Correct single-key LLSD map", is_single_key_map(sd, region1.asString())); + sd = sd[region1.asString()]; + + // Check a few points on the tree for content + ensure("sd[get_gesture_udp][enqueued] is 0", (0 == sd["get_gesture_udp"]["enqueued"].asInteger())); + ensure("sd[get_gesture_udp][dequeued] is 0", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); + + ensure("sd[get_wearable_udp][enqueued] is 4", (4 == sd["get_wearable_udp"]["enqueued"].asInteger())); + ensure("sd[get_wearable_udp][dequeued] is 4", (4 == sd["get_wearable_udp"]["dequeued"].asInteger())); + + ensure("sd[get_other][enqueued] is 4", (4 == sd["get_other"]["enqueued"].asInteger())); + ensure("sd[get_other][dequeued] is 0", (0 == sd["get_other"]["dequeued"].asInteger())); + + // Reset and check zeros... + // Reset leaves current region in place + gViewerAssetStatsMain->reset(); + sd = gViewerAssetStatsMain->asLLSD()[region1.asString()]; - delete gViewerAssetStats; - gViewerAssetStats = NULL; + delete gViewerAssetStatsMain; + gViewerAssetStatsMain = NULL; + delete gViewerAssetStatsThread1; + gViewerAssetStatsThread1 = NULL; ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); -- cgit v1.2.3 From deeef0c73ead965f7202bb5ac4c8481354f3b08e Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Wed, 10 Nov 2010 10:13:31 -0800 Subject: Need precompiled header include for windows. --- indra/newview/llviewerassetstats.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index a6c4685bf1..37e7c43f36 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -30,6 +30,8 @@ * $/LicenseInfo$ */ +#include "llviewerprecompiledheaders.h" + #include "llviewerassetstats.h" #include "stdtypes.h" -- cgit v1.2.3 From 746b2c00e6f09b9d3a3f72805d5e208b5e3b5f6b Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 12 Nov 2010 14:16:48 -0800 Subject: EXP-377 FIX Update LLQTWebkit to 4.7.1 (Windows version) --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index 391d83b224..60c4290bf4 100644 --- a/install.xml +++ b/install.xml @@ -995,9 +995,9 @@ anguage Infrstructure (CLI) international standard windows md5sum - 4b8412833c00f8cdaba26808f0ddb404 + adbee46dda6db661cbdb327463e70532 url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.6-20100916.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101112.tar.bz2 -- cgit v1.2.3 From 04adbdad4bb13cb98c77bba17fcc9a16e0f44203 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 12 Nov 2010 16:37:42 -0800 Subject: STORM-151 : Got decompression to work, compression disabled, simplified llkdu building --- indra/cmake/LLKDU.cmake | 4 +--- indra/llkdu/CMakeLists.txt | 22 ++-------------------- indra/llkdu/llblockdecoder.cpp | 13 +++++-------- indra/llkdu/llblockencoder.cpp | 13 +++++-------- indra/llkdu/llimagej2ckdu.cpp | 26 ++++++++++++++++++-------- indra/llkdu/llimagej2ckdu.h | 10 +++++----- indra/llkdu/llkdumem.cpp | 3 ++- indra/llkdu/llkdumem.h | 13 +++++++------ indra/newview/CMakeLists.txt | 2 +- 9 files changed, 46 insertions(+), 60 deletions(-) diff --git a/indra/cmake/LLKDU.cmake b/indra/cmake/LLKDU.cmake index 25703ee785..0c103e89d2 100644 --- a/indra/cmake/LLKDU.cmake +++ b/indra/cmake/LLKDU.cmake @@ -15,10 +15,8 @@ if (USE_KDU) set(KDU_LIBRARY kdu) endif (WINDOWS) - set(KDU_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) + set(KDU_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/kdu) set(LLKDU_LIBRARY llkdu) - set(LLKDU_STATIC_LIBRARY llkdu_static) set(LLKDU_LIBRARIES ${LLKDU_LIBRARY}) - set(LLKDU_STATIC_LIBRARIES ${LLKDU_STATIC_LIBRARY}) endif (USE_KDU) diff --git a/indra/llkdu/CMakeLists.txt b/indra/llkdu/CMakeLists.txt index 2806af26c3..0932d368b5 100644 --- a/indra/llkdu/CMakeLists.txt +++ b/indra/llkdu/CMakeLists.txt @@ -25,26 +25,12 @@ include_directories( ) set(llkdu_SOURCE_FILES - kdc_flow_control.cpp - kde_flow_control.cpp - kdu_image.cpp - llblockdata.cpp - llblockdecoder.cpp - llblockencoder.cpp llimagej2ckdu.cpp llkdumem.cpp ) set(llkdu_HEADER_FILES CMakeLists.txt - - kdc_flow_control.h - kde_flow_control.h - kdu_image.h - kdu_image_local.h - llblockdata.h - llblockdecoder.h - llblockencoder.h llimagej2ckdu.h llkdumem.h ) @@ -71,15 +57,11 @@ if (WINDOWS) endif (WINDOWS) if (LLKDU_LIBRARY) - add_library (${LLKDU_STATIC_LIBRARY} ${llkdu_SOURCE_FILES}) + add_library (${LLKDU_LIBRARY} ${llkdu_SOURCE_FILES}) target_link_libraries( - ${LLKDU_STATIC_LIBRARY} -# ${LLIMAGE_LIBRARIES} -# ${LLVFS_LIBRARIES} + ${LLKDU_LIBRARY} ${LLMATH_LIBRARIES} -# ${LLCOMMON_LIBRARIES} ${KDU_LIBRARY} -# ${WINDOWS_LIBRARIES} ) endif (LLKDU_LIBRARY) diff --git a/indra/llkdu/llblockdecoder.cpp b/indra/llkdu/llblockdecoder.cpp index b4ddb2fba2..3daa016591 100644 --- a/indra/llkdu/llblockdecoder.cpp +++ b/indra/llkdu/llblockdecoder.cpp @@ -29,14 +29,11 @@ #include "llblockdecoder.h" // KDU core header files -#include "kdu/kdu_elementary.h" -#include "kdu/kdu_messaging.h" -#include "kdu/kdu_params.h" -#include "kdu/kdu_compressed.h" -#include "kdu/kdu_sample_processing.h" - -// KDU utility functions. -#include "kde_flow_control.h" +#include "kdu_elementary.h" +#include "kdu_messaging.h" +#include "kdu_params.h" +#include "kdu_compressed.h" +#include "kdu_sample_processing.h" #include "llkdumem.h" diff --git a/indra/llkdu/llblockencoder.cpp b/indra/llkdu/llblockencoder.cpp index f19841e36f..759eaf65f9 100644 --- a/indra/llkdu/llblockencoder.cpp +++ b/indra/llkdu/llblockencoder.cpp @@ -29,14 +29,11 @@ #include "llblockencoder.h" // KDU core header files -#include "kdu/kdu_elementary.h" -#include "kdu/kdu_messaging.h" -#include "kdu/kdu_params.h" -#include "kdu/kdu_compressed.h" -#include "kdu/kdu_sample_processing.h" - -// KDU utility functions. -#include "kdc_flow_control.h" +#include "kdu_elementary.h" +#include "kdu_messaging.h" +#include "kdu_params.h" +#include "kdu_compressed.h" +#include "kdu_sample_processing.h" #include "llkdumem.h" diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 1785aa111d..147b9829c5 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -27,15 +27,10 @@ #include "linden_common.h" #include "llimagej2ckdu.h" -// KDU utility functions. -#include "kde_flow_control.h" -#include "kdc_flow_control.h" - #include "lltimer.h" #include "llpointer.h" #include "llkdumem.h" - // // Kakadu specific implementation // @@ -113,7 +108,8 @@ void ll_kdu_error( void ) class LLKDUMessageWarning : public kdu_message { public: - /*virtual*/ void put_text(const char *string); + /*virtual*/ void put_text(const char *s); + /*virtual*/ void put_text(const kdu_uint16 *s); static LLKDUMessageWarning sDefaultMessage; }; @@ -121,7 +117,8 @@ public: class LLKDUMessageError : public kdu_message { public: - /*virtual*/ void put_text(const char *string); + /*virtual*/ void put_text(const char *s); + /*virtual*/ void put_text(const kdu_uint16 *s); /*virtual*/ void flush(bool end_of_message=false); static LLKDUMessageError sDefaultMessage; }; @@ -131,11 +128,21 @@ void LLKDUMessageWarning::put_text(const char *s) llinfos << "KDU Warning: " << s << llendl; } +void LLKDUMessageWarning::put_text(const kdu_uint16 *s) +{ + llinfos << "KDU Warning: " << s << llendl; +} + void LLKDUMessageError::put_text(const char *s) { llinfos << "KDU Error: " << s << llendl; } +void LLKDUMessageError::put_text(const kdu_uint16 *s) +{ + llinfos << "KDU Error: " << s << llendl; +} + void LLKDUMessageError::flush(bool end_of_message) { if( end_of_message ) @@ -467,7 +474,7 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible) { // Collect simple arguments. - +/* bool transpose, vflip, hflip; bool allow_rate_prediction, allow_shorts, mem, quiet, no_weights; int cpu_iterations; @@ -685,6 +692,9 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co } return TRUE; + */ + // Compression not implemented yet + return FALSE; } BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base) diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h index 5794ebdc68..ac0443d8fc 100644 --- a/indra/llkdu/llimagej2ckdu.h +++ b/indra/llkdu/llimagej2ckdu.h @@ -33,11 +33,11 @@ // // // KDU core header files -#include "kdu/kdu_elementary.h" -#include "kdu/kdu_messaging.h" -#include "kdu/kdu_params.h" -#include "kdu/kdu_compressed.h" -#include "kdu/kdu_sample_processing.h" +#include "kdu_elementary.h" +#include "kdu_messaging.h" +#include "kdu_params.h" +#include "kdu_compressed.h" +#include "kdu_sample_processing.h" class LLKDUDecodeState; class LLKDUMemSource; diff --git a/indra/llkdu/llkdumem.cpp b/indra/llkdu/llkdumem.cpp index 80f4c444d1..811c5b52bb 100644 --- a/indra/llkdu/llkdumem.cpp +++ b/indra/llkdu/llkdumem.cpp @@ -199,7 +199,7 @@ bool LLKDUMemIn::get(int comp_idx, kdu_line_buf &line, int x_tnum) } - +/* LLKDUMemOut::LLKDUMemOut(U8 *data, siz_params *siz, U8 in_num_components) { int is_signed = 0; @@ -390,3 +390,4 @@ void LLKDUMemOut::put(int comp_idx, kdu_line_buf &line, int x_tnum) free_lines = scan; } } +*/ \ No newline at end of file diff --git a/indra/llkdu/llkdumem.h b/indra/llkdu/llkdumem.h index fecb4653db..f0580cf84f 100644 --- a/indra/llkdu/llkdumem.h +++ b/indra/llkdu/llkdumem.h @@ -30,11 +30,11 @@ // Support classes for reading and writing from memory buffers // for KDU #include "kdu_image.h" -#include "kdu/kdu_elementary.h" -#include "kdu/kdu_messaging.h" -#include "kdu/kdu_params.h" -#include "kdu/kdu_compressed.h" -#include "kdu/kdu_sample_processing.h" +#include "kdu_elementary.h" +#include "kdu_messaging.h" +#include "kdu_params.h" +#include "kdu_compressed.h" +#include "kdu_sample_processing.h" #include "kdu_image_local.h" #include "stdtypes.h" @@ -142,6 +142,7 @@ private: // Data U32 mDataSize; }; +/* class LLKDUMemOut : public kdu_image_out_base { public: // Member functions @@ -163,5 +164,5 @@ private: // Data U32 mCurPos; U32 mDataSize; }; - +*/ #endif diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 2515321a6c..8d6c9d7f7b 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1675,7 +1675,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} if (LLKDU_LIBRARY) target_link_libraries(${VIEWER_BINARY_NAME} - ${LLKDU_STATIC_LIBRARIES} + ${LLKDU_LIBRARIES} ${KDU_LIBRARY} ) else (LLKDU_LIBRARY) -- cgit v1.2.3 From b76a2a3e95e639a8d49fe7159103fd4e26a4faa2 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Fri, 12 Nov 2010 18:38:44 -0800 Subject: EXP-377 FIX Update LLQTWebkit to 4.7.1 (Mac version) NOTE: since I don't have the proper S3 keys to upload the library build at the moment, this is currently an scp link to install-packages.lindenlab.com. Once the package is uploaded to S3, the link will need to be fixed. --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index 60c4290bf4..e20fd1f995 100644 --- a/install.xml +++ b/install.xml @@ -981,9 +981,9 @@ anguage Infrstructure (CLI) international standard darwin md5sum - 34d9e4c93678a422cf80521bf0cd7628 + 1b44c0dfb42faad087d2cd46a96c1f1b url - http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/llqtwebkit-4.6-darwin-20100914.tar.bz2 + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/llqtwebkit-darwin-qt4.7.1-20101112.tar.bz2 linux -- cgit v1.2.3 From a52e06d209925d1942230e8c129d8b19af7b88b5 Mon Sep 17 00:00:00 2001 From: callum Date: Mon, 15 Nov 2010 15:27:18 -0800 Subject: Change to Qt 4.7.1 built version of LLQtWebKit. (Only a change to manifest packaging) --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index e20fd1f995..23e5128f14 100644 --- a/install.xml +++ b/install.xml @@ -995,9 +995,9 @@ anguage Infrstructure (CLI) international standard windows md5sum - adbee46dda6db661cbdb327463e70532 + d172a43efff930066a22100e3ab74406 url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101112.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101115.tar.bz2 -- cgit v1.2.3 From e3d95ddb9a3e6abc8e800edf77cf3b0e4f5c4b8f Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 15 Nov 2010 21:28:16 -0800 Subject: STORM-151 : Make kdu decompression work without ugly hack in library header names --- indra/llkdu/llkdumem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llkdu/llkdumem.h b/indra/llkdu/llkdumem.h index f0580cf84f..b1b2516095 100644 --- a/indra/llkdu/llkdumem.h +++ b/indra/llkdu/llkdumem.h @@ -35,7 +35,7 @@ #include "kdu_params.h" #include "kdu_compressed.h" #include "kdu_sample_processing.h" -#include "kdu_image_local.h" +#include "image_local.h" #include "stdtypes.h" class LLKDUMemSource: public kdu_compressed_source -- cgit v1.2.3 From 5397edebbccd2df41db51804c4e2fa529ac96132 Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 16 Nov 2010 15:11:32 -0800 Subject: SOCIAL-265 FIX Help floater in client should bypass the usual media MIME type detection --- indra/newview/llfloaterhelpbrowser.cpp | 7 ++++--- indra/newview/skins/default/xui/en/floater_help_browser.xml | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/indra/newview/llfloaterhelpbrowser.cpp b/indra/newview/llfloaterhelpbrowser.cpp index cec98e9992..a650886d89 100644 --- a/indra/newview/llfloaterhelpbrowser.cpp +++ b/indra/newview/llfloaterhelpbrowser.cpp @@ -132,9 +132,10 @@ void LLFloaterHelpBrowser::onClickOpenWebBrowser(void* user_data) void LLFloaterHelpBrowser::openMedia(const std::string& media_url) { - mBrowser->setHomePageUrl(media_url); - //mBrowser->navigateTo("data:text/html;charset=utf-8,I'd really love to be going to:
" + media_url + ""); // tofu HACK for debugging =:) - mBrowser->navigateTo(media_url); + // explicitly make the media mime type for this floater since it will + // only ever display one type of content (Web). + mBrowser->setHomePageUrl(media_url, "text/html"); + mBrowser->navigateTo(media_url, "text/html"); setCurrentURL(media_url); } diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml index 837923bcf6..02e50ee584 100644 --- a/indra/newview/skins/default/xui/en/floater_help_browser.xml +++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml @@ -36,7 +36,8 @@ user_resize="false" width="620"> Date: Tue, 16 Nov 2010 17:01:44 -0800 Subject: SOCIAL-266 WIP HTTP AUTH dialogs no longer work in LLQtWebKit 4.7.1 Added support to the webkit media plugin and llpluginclassmedia for passing through the auth request/response. We still need an updated build of llqtwebkit for all platforms, as well as some UI work in the viewer to actually display the auth dialog. --- indra/llplugin/llpluginclassmedia.cpp | 20 +++++++++++ indra/llplugin/llpluginclassmedia.h | 8 +++++ indra/llplugin/llpluginclassmediaowner.h | 4 ++- indra/media_plugins/webkit/media_plugin_webkit.cpp | 41 ++++++++++++++++++++++ indra/newview/llmediactrl.cpp | 6 ++++ indra/newview/llviewermedia.cpp | 8 +++++ indra/newview/llviewerparcelmedia.cpp | 6 ++++ indra/test_apps/llplugintest/llmediaplugintest.cpp | 9 +++++ 8 files changed, 101 insertions(+), 1 deletion(-) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 446df646fc..cd0689caa6 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -682,6 +682,20 @@ void LLPluginClassMedia::sendPickFileResponse(const std::string &file) sendMessage(message); } +void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response"); + message.setValueBoolean("ok", ok); + message.setValue("username", username); + message.setValue("password", password); + if(mPlugin->isBlocked()) + { + // If the plugin sent a blocking pick-file request, the response should unblock it. + message.setValueBoolean("blocking_response", true); + } + sendMessage(message); +} + void LLPluginClassMedia::cut() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut"); @@ -947,6 +961,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST); } + else if(message_name == "auth_request") + { + mAuthURL = message.getValue("url"); + mAuthRealm = message.getValue("realm"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST); + } else { LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 938e5c1bf6..2b8a7238b5 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -159,6 +159,8 @@ public: void sendPickFileResponse(const std::string &file); + void sendAuthResponse(bool ok, const std::string &username, const std::string &password); + // Valid after a MEDIA_EVENT_CURSOR_CHANGED event std::string getCursorName() const { return mCursorName; }; @@ -232,6 +234,10 @@ public: S32 getGeometryY() const { return mGeometryY; }; S32 getGeometryWidth() const { return mGeometryWidth; }; S32 getGeometryHeight() const { return mGeometryHeight; }; + + // These are valid during MEDIA_EVENT_AUTH_REQUEST + std::string getAuthURL() const { return mAuthURL; }; + std::string getAuthRealm() const { return mAuthRealm; }; std::string getMediaName() const { return mMediaName; }; std::string getMediaDescription() const { return mMediaDescription; }; @@ -370,6 +376,8 @@ protected: S32 mGeometryY; S32 mGeometryWidth; S32 mGeometryHeight; + std::string mAuthURL; + std::string mAuthRealm; ///////////////////////////////////////// // media_time class diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h index c9efff216c..42a89baebc 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -59,7 +59,9 @@ public: MEDIA_EVENT_GEOMETRY_CHANGE, // The plugin requested its window geometry be changed (per the javascript window interface) MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch - MEDIA_EVENT_PLUGIN_FAILED // The plugin died unexpectedly + MEDIA_EVENT_PLUGIN_FAILED, // The plugin died unexpectedly + + MEDIA_EVENT_AUTH_REQUEST // The plugin wants to display an auth dialog } EMediaEvent; diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 15c107cbe1..5dbc2f9fdf 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -569,6 +569,43 @@ private: return blockingPickFile(); } + std::string mAuthUsername; + std::string mAuthPassword; + bool mAuthOK; + + //////////////////////////////////////////////////////////////////////////////// + // virtual + bool onAuthRequest(const std::string &in_url, const std::string &in_realm, std::string &out_username, std::string &out_password) + { + mAuthOK = false; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_request"); + message.setValue("url", in_url); + message.setValue("realm", in_realm); + message.setValueBoolean("blocking_request", true); + + // The "blocking_request" key in the message means this sendMessage call will block until a response is received. + sendMessage(message); + + if(mAuthOK) + { + out_username = mAuthUsername; + out_password = mAuthPassword; + } + + return mAuthOK; + } + + void authResponse(LLPluginMessage &message) + { + mAuthOK = message.getValueBoolean("ok"); + if(mAuthOK) + { + mAuthUsername = message.getValue("username"); + mAuthPassword = message.getValue("password"); + } + } + LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers) { int result = 0; @@ -1096,6 +1133,10 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) { onPickFileResponse(message_in.getValue("file")); } + if(message_name == "auth_response") + { + authResponse(message_in); + } else { // std::cerr << "MediaPluginWebKit::receiveMessage: unknown media message: " << message_string << std::endl; diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 5e27004ed8..0a5263d1ab 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -1092,6 +1092,12 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL; } break; + + case MEDIA_EVENT_AUTH_REQUEST: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() << ", realm " << self->getAuthRealm() << LL_ENDL; + } + break; }; // chain all events to any potential observers of this object. diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 7c65f375ca..0d13a0a263 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -3008,6 +3008,14 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla plugin->sendPickFileResponse(response); } break; + + case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST: + { + llinfos << "MEDIA_EVENT_AUTH_REQUEST, url " << plugin->getAuthURL() << ", realm " << plugin->getAuthRealm() << LL_ENDL; + + // TODO: open an auth dialog that will call this when complete + plugin->sendAuthResponse(false, "", ""); + } case LLViewerMediaObserver::MEDIA_EVENT_CLOSE_REQUEST: { diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 99e869dafc..41e59c626d 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -586,6 +586,12 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_GEOMETRY_CHANGE, uuid is " << self->getClickUUID() << LL_ENDL; } break; + + case MEDIA_EVENT_AUTH_REQUEST: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() << ", realm " << self->getAuthRealm() << LL_ENDL; + } + break; }; } diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index 873fa23db8..f2a10bc264 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -2220,6 +2220,15 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e << ", height = " << self->getGeometryHeight() << std::endl; break; + + case MEDIA_EVENT_AUTH_REQUEST: + { + std::cerr << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() ", realm " << self->getAuthRealm() << std::endl; + + // TODO: display an auth dialog + self->sendAuthResponse(false, "", ""); + } + break; } } -- cgit v1.2.3 From 9ebbc46608edfc93fe8fdecc4af793e99a1f13d4 Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 16 Nov 2010 17:43:04 -0800 Subject: SOCIAL-266 (PARTIAL FIX) Implement solution for HTTP dialogs that don't work in 4.7.1 This change is a new version of LLQtWebKit to support the changes --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index 23e5128f14..69ff995b39 100644 --- a/install.xml +++ b/install.xml @@ -995,9 +995,9 @@ anguage Infrstructure (CLI) international standard windows md5sum - d172a43efff930066a22100e3ab74406 + 7fb495bee8f25e41804ca472a2275506 url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101115.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101116.tar.bz2 -- cgit v1.2.3 From c300ebffe8ed89aa2877bf283ed13571f9bf415d Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Tue, 16 Nov 2010 17:43:53 -0800 Subject: SOCIAL-266 WIP HTTP AUTH dialogs no longer work in LLQtWebKit 4.7.1 New Mac build of llqtwebkit from this revision: http://hg.secondlife.com/llqtwebkit/changeset/d5876292d3d3 --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index 69ff995b39..8bdfc424b7 100644 --- a/install.xml +++ b/install.xml @@ -981,9 +981,9 @@ anguage Infrstructure (CLI) international standard darwin md5sum - 1b44c0dfb42faad087d2cd46a96c1f1b + 2a272816119ff5da1712ad7a49fc9c51 url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/llqtwebkit-darwin-qt4.7.1-20101112.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-darwin-qt4.7.1-20101116.bz2 linux -- cgit v1.2.3 From 5b69eeca918ca15c9cc2827286eb477b334089a2 Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 16 Nov 2010 17:55:31 -0800 Subject: SOCIAL-269 FIX Search floater in client should bypass the usual media MIME type detection --- indra/newview/llfloatersearch.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 3ed4aec89a..2041fac8d8 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -200,5 +200,5 @@ void LLFloaterSearch::search(const LLSD &key) url = LLWeb::expandURLSubstitutions(url, subs); // and load the URL in the web view - mBrowser->navigateTo(url); + mBrowser->navigateTo(url, "text/html"); } -- cgit v1.2.3 From 9d82af29df47e731749f9a346a630356975153d2 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Wed, 17 Nov 2010 16:01:46 -0800 Subject: SOCIAL-233 WIP Better performance (improve loading time of webkit instance) The plugin system will now keep a spare running webkit plugin process around and use it when it needs a webkit instance. This should hide some large portion of the setup time when creating a new webkit plugin (i.e. opening the search window, etc.) --- indra/llplugin/llpluginclassmedia.cpp | 2 +- indra/llplugin/llpluginclassmedia.h | 2 ++ indra/newview/llviewermedia.cpp | 50 ++++++++++++++++++++++++++++++++++- indra/newview/llviewermedia.h | 4 +++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index cd0689caa6..4001cb183f 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -160,7 +160,7 @@ void LLPluginClassMedia::idle(void) mPlugin->idle(); } - if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked())) + if((mMediaWidth == -1) || (!mTextureParamsReceived) || (mPlugin == NULL) || (mPlugin->isBlocked()) || (mOwner == NULL)) { // Can't process a size change at this time } diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 2b8a7238b5..562e3620ec 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -85,6 +85,8 @@ public: void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; }; + void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; }; + // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent. // This will initially be false, and will also be false for some time after setSize while the resize is processed. // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 0d13a0a263..bcac6533e6 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -293,6 +293,7 @@ public: LLPluginCookieStore *LLViewerMedia::sCookieStore = NULL; LLURL LLViewerMedia::sOpenIDURL; std::string LLViewerMedia::sOpenIDCookie; +LLPluginClassMedia* LLViewerMedia::sSpareBrowserMediaSource = NULL; static LLViewerMedia::impl_list sViewerMediaImplList; static LLViewerMedia::impl_id_map sViewerMediaTextureIDMap; static LLTimer sMediaCreateTimer; @@ -742,6 +743,9 @@ void LLViewerMedia::updateMedia(void *dummy_arg) // Enable/disable the plugin read thread LLPluginProcessParent::setUseReadThread(gSavedSettings.getBOOL("PluginUseReadThread")); + // HACK: we always try to keep a spare running webkit plugin around to improve launch times. + createSpareBrowserMediaSource(); + sAnyMediaShowing = false; sUpdatedCookies = getCookieStore()->getChangedCookies(); if(!sUpdatedCookies.empty()) @@ -759,6 +763,12 @@ void LLViewerMedia::updateMedia(void *dummy_arg) pimpl->update(); pimpl->calculateInterest(); } + + // Let the spare media source actually launch + if(sSpareBrowserMediaSource) + { + sSpareBrowserMediaSource->idle(); + } // Sort the static instance list using our interest criteria sViewerMediaImplList.sort(priorityComparitor); @@ -1400,6 +1410,29 @@ void LLViewerMedia::proxyWindowClosed(const std::string &uuid) } } +///////////////////////////////////////////////////////////////////////////////////////// +// static +void LLViewerMedia::createSpareBrowserMediaSource() +{ + if(!sSpareBrowserMediaSource) + { + // If we don't have a spare browser media source, create one. + // The null owner will keep the browser plugin from fully initializing + // (specifically, it keeps LLPluginClassMedia from negotiating a size change, + // which keeps MediaPluginWebkit::initBrowserWindow from doing anything until we have some necessary data, like the background color) + sSpareBrowserMediaSource = LLViewerMediaImpl::newSourceFromMediaType("text/html", NULL, 0, 0); + } +} + +///////////////////////////////////////////////////////////////////////////////////////// +// static +LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource() +{ + LLPluginClassMedia* result = sSpareBrowserMediaSource; + sSpareBrowserMediaSource = NULL; + return result; +}; + bool LLViewerMedia::hasInWorldMedia() { if (sInWorldMediaDisabled) return false; @@ -1636,6 +1669,21 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type) LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_type, LLPluginClassMediaOwner *owner /* may be NULL */, S32 default_width, S32 default_height, const std::string target) { std::string plugin_basename = LLMIMETypes::implType(media_type); + LLPluginClassMedia* media_source = NULL; + + // HACK: we always try to keep a spare running webkit plugin around to improve launch times. + if(plugin_basename == "media_plugin_webkit") + { + media_source = LLViewerMedia::getSpareBrowserMediaSource(); + if(media_source) + { + media_source->setOwner(owner); + media_source->setTarget(target); + media_source->setSize(default_width, default_height); + + return media_source; + } + } if(plugin_basename.empty()) { @@ -1673,7 +1721,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ } else { - LLPluginClassMedia* media_source = new LLPluginClassMedia(owner); + media_source = new LLPluginClassMedia(owner); media_source->setSize(default_width, default_height); media_source->setUserDataPath(user_data_path); media_source->setLanguageCode(LLUI::getLanguage()); diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 4025a4484f..6f8d12e676 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -155,6 +155,9 @@ public: static void proxyWindowOpened(const std::string &target, const std::string &uuid); static void proxyWindowClosed(const std::string &uuid); + static void createSpareBrowserMediaSource(); + static LLPluginClassMedia* getSpareBrowserMediaSource(); + private: static void setOpenIDCookie(); static void onTeleportFinished(); @@ -162,6 +165,7 @@ private: static LLPluginCookieStore *sCookieStore; static LLURL sOpenIDURL; static std::string sOpenIDCookie; + static LLPluginClassMedia* sSpareBrowserMediaSource; }; // Implementation functions not exported into header file -- cgit v1.2.3 From d666a3d92cb5dd9844c29e5472db542de7b5ac9e Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Thu, 18 Nov 2010 08:43:09 -0800 Subject: ESC-154 ESC-155 ESC-156 Asset fetch requests wrapped to allow for measurements. Asset fetch enqueues, dequeues and completion times recorded to asset stats collector. Texture fetch operations (http and udp) recorded to asset stats collector. Stats collector time vallue switched from F32 to U64 which is the more common type in the viewer. Cross-thread mechanism introduced to communicate region changes and generate global statistics messages. Facility to deliver metrics via Capabilities sketched in but needs additional work. Documentation and diagrams added. --- indra/newview/llagent.cpp | 3 + indra/newview/llappviewer.cpp | 114 ++++++ indra/newview/llappviewer.h | 4 + indra/newview/lltexturefetch.cpp | 488 +++++++++++++++++++++++- indra/newview/lltexturefetch.h | 33 +- indra/newview/llviewerassetstats.cpp | 87 ++++- indra/newview/llviewerassetstats.h | 48 ++- indra/newview/llviewerassetstorage.cpp | 124 ++++++ indra/newview/llviewerassetstorage.h | 11 + indra/newview/llviewerregion.cpp | 1 + indra/newview/tests/llviewerassetstats_test.cpp | 2 +- 11 files changed, 893 insertions(+), 22 deletions(-) diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index c9bd7851ed..e2b1c89402 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -637,6 +637,9 @@ void LLAgent::setRegion(LLViewerRegion *regionp) // Update all of the regions. LLWorld::getInstance()->updateAgentOffset(mAgentOriginGlobal); } + + // Pass new region along to metrics components that care about this level of detail. + LLAppViewer::metricsUpdateRegion(regionp->getRegionID()); } mRegionp = regionp; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 333c92e50d..2e056238e4 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -190,6 +190,7 @@ #include "llparcel.h" #include "llavatariconctrl.h" #include "llgroupiconctrl.h" +#include "llviewerassetstats.h" // Include for security api initialization #include "llsecapi.h" @@ -332,6 +333,14 @@ static std::string gWindowTitle; LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ; +//---------------------------------------------------------------------------- +// Metrics logging control constants +//---------------------------------------------------------------------------- +static const F32 METRICS_INTERVAL_MIN = 300.0; +static const F32 METRICS_INTERVAL_MAX = 3600.0; +static const F32 METRICS_INTERVAL_DEFAULT = 600.0; + + void idle_afk_check() { // check idle timers @@ -656,6 +665,8 @@ bool LLAppViewer::init() LLCurl::initClass(); LLMachineID::init(); + LLViewerAssetStatsFF::init(); + initThreads(); writeSystemInfo(); @@ -1670,6 +1681,8 @@ bool LLAppViewer::cleanup() LLWatchdog::getInstance()->cleanup(); + LLViewerAssetStatsFF::cleanup(); + llinfos << "Shutting down message system" << llendflush; end_messaging_system(); @@ -3683,6 +3696,18 @@ void LLAppViewer::idle() gInventory.idleNotifyObservers(); } + // Metrics logging (LLViewerAssetStats, etc.) + { + static LLTimer report_interval; + + // *TODO: Add configuration controls for this + if (report_interval.getElapsedTimeF32() >= METRICS_INTERVAL_DEFAULT) + { + metricsIdle(! gDisconnected); + report_interval.reset(); + } + } + if (gDisconnected) { return; @@ -4525,3 +4550,92 @@ bool LLAppViewer::getMasterSystemAudioMute() { return gSavedSettings.getBOOL("MuteAudio"); } + +//---------------------------------------------------------------------------- +// Metrics-related methods (static and otherwise) +//---------------------------------------------------------------------------- + +/** + * LLViewerAssetStats collects data on a per-region (as defined by the agent's + * location) so we need to tell it about region changes which become a kind of + * hidden variable/global state in the collectors. For collectors not running + * on the main thread, we need to send a message to move the data over safely + * and cheaply (amortized over a run). + */ +void LLAppViewer::metricsUpdateRegion(const LLUUID & region_id) +{ + if (! region_id.isNull()) + { + LLViewerAssetStatsFF::set_region_main(region_id); + if (LLAppViewer::sTextureFetch) + { + // Send a region update message into 'thread1' to get the new region. + LLAppViewer::sTextureFetch->commandSetRegion(region_id); + } + else + { + // No 'thread1', a.k.a. TextureFetch, so update directly + LLViewerAssetStatsFF::set_region_thread1(region_id); + } + } +} + + +/** + * Attempts to start a multi-threaded metrics report to be sent back to + * the grid for consumption. + */ +void LLAppViewer::metricsIdle(bool enable_reporting) +{ + if (! gViewerAssetStatsMain) + return; + + std::string caps_url; + LLViewerRegion * regionp = gAgent.getRegion(); + if (regionp) + { + caps_url = regionp->getCapability("ViewerMetrics"); + caps_url = "http://localhost:80/putz/"; + } + + if (enable_reporting && regionp && ! caps_url.empty()) + { + // *NOTE: Pay attention here. LLSD's are not safe for thread sharing + // and their ownership is difficult to transfer across threads. We do + // it here by having only one reference (the new'd pointer) to the LLSD + // or any subtree of it. This pointer is then transfered to the other + // thread using correct thread logic. + + LLSD * envelope = new LLSD(LLSD::emptyMap()); + { + (*envelope)["session_id"] = gAgentSessionID; + (*envelope)["agent_id"] = gAgentID; + (*envelope)["regions"] = gViewerAssetStatsMain->asLLSD(); + } + + if (LLAppViewer::sTextureFetch) + { + // Send a report request into 'thread1' to get the rest of the data + // and have it sent to the stats collector. LLSD ownership transfers + // with this call. + LLAppViewer::sTextureFetch->commandSendMetrics(caps_url, envelope); + envelope = 0; // transfer noted + } + else + { + // No 'thread1' so transfer doesn't happen and we need to clean up + delete envelope; + envelope = 0; + } + } + else + { + LLAppViewer::sTextureFetch->commandDataBreak(); + } + + // Reset even if we can't report. Rather than gather up a huge chunk of + // data, we'll keep to our sampling interval and retain the data + // resolution in time. + gViewerAssetStatsMain->reset(); +} + diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 56d88f07c8..909f191ab1 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -167,6 +167,10 @@ public: // mute/unmute the system's master audio virtual void setMasterSystemAudioMute(bool mute); virtual bool getMasterSystemAudioMute(); + + // Metrics policy helper statics. + static void metricsUpdateRegion(const LLUUID & region_id); + static void metricsIdle(bool enable_reporting); protected: virtual bool initWindow(); // Initialize the viewer's window. diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index fafef84aa2..df99818ee9 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -49,6 +49,7 @@ #include "llviewertexture.h" #include "llviewerregion.h" #include "llviewerstats.h" +#include "llviewerassetstats.h" #include "llworld.h" ////////////////////////////////////////////////////////////////////////////// @@ -143,7 +144,7 @@ public: /*virtual*/ bool deleteOK(); // called from update() (WORK THREAD) ~LLTextureFetchWorker(); - void relese() { --mActiveCount; } + // void relese() { --mActiveCount; } S32 callbackHttpGet(const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer, @@ -161,9 +162,11 @@ public: mGetReason = reason; } - void setCanUseHTTP(bool can_use_http) {mCanUseHTTP = can_use_http;} - bool getCanUseHTTP()const {return mCanUseHTTP ;} + void setCanUseHTTP(bool can_use_http) { mCanUseHTTP = can_use_http; } + bool getCanUseHTTP() const { return mCanUseHTTP; } + LLTextureFetch & getFetcher() { return *mFetcher; } + protected: LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 discard, S32 size); @@ -277,6 +280,8 @@ private: S32 mLastPacket; U16 mTotalPackets; U8 mImageCodec; + + LLViewerAssetStats::duration_t mMetricsStartTime; }; ////////////////////////////////////////////////////////////////////////////// @@ -333,6 +338,18 @@ public: S32 data_size = worker->callbackHttpGet(channels, buffer, partial, success); mFetcher->removeFromHTTPQueue(mID, data_size); + + if (worker->mMetricsStartTime) + { + LLViewerAssetStatsFF::record_response_thread1(LLViewerAssetType::AT_TEXTURE, + true, + LLImageBase::TYPE_AVATAR_BAKE == worker->mType, + LLViewerAssetStatsFF::get_timestamp() - worker->mMetricsStartTime); + worker->mMetricsStartTime = 0; + } + LLViewerAssetStatsFF::record_dequeue_thread1(LLViewerAssetType::AT_TEXTURE, + true, + LLImageBase::TYPE_AVATAR_BAKE == worker->mType); } else { @@ -355,6 +372,201 @@ private: bool mFollowRedir; }; +////////////////////////////////////////////////////////////////////////////// + +// Cross-thread messaging for asset metrics. + +namespace +{ + +/** + * @brief Base class for cross-thread requests made of the fetcher + * + * I believe the intent of the LLQueuedThread class was to + * have these operations derived from LLQueuedThread::QueuedRequest + * but the texture fetcher has elected to manage the queue + * in its own manner. So these are free-standing objects which are + * managed in simple FIFO order on the mCommands queue of the + * LLTextureFetch object. + * + * What each represents is a simple command sent from an + * outside thread into the TextureFetch thread to be processed + * in order and in a timely fashion (though not an absolute + * higher priority than other operations of the thread). + * Each operation derives a new class from the base customizing + * members, constructors and the doWork() method to effect + * the command. + * + * The flow is one-directional. There are two global instances + * of the LLViewerAssetStats collector, one for the main program's + * thread pointed to by gViewerAssetStatsMain and one for the + * TextureFetch thread pointed to by gViewerAssetStatsThread1. + * Common operations has each thread recording metrics events + * into the respective collector unconcerned with locking and + * the state of any other thread. But when the agent moves into + * a different region or the metrics timer expires and a report + * needs to be sent back to the grid, messaging across grids + * is required to distribute data and perform global actions. + * In pseudo-UML, it looks like: + * + * Main Thread1 + * . . + * . . + * +-----+ . + * | AM | . + * +--+--+ . + * +-------+ | . + * | Main | +--+--+ . + * | | | SRE |---. . + * | Stats | +-----+ \ . + * | | | \ (uuid) +-----+ + * | Coll. | +--+--+ `-------->| SR | + * +-------+ | MSC | +--+--+ + * | ^ +-----+ | + * | | (uuid) / . +-----+ (uuid) + * | `--------' . | MSC |---------. + * | . +-----+ | + * | +-----+ . v + * | | TE | . +-------+ + * | +--+--+ . | Thd1 | + * | | . | | + * | (llsd) +-----+ . | Stats | + * `--------->| RSC | . | | + * +--+--+ . | Coll. | + * | . +-------+ + * +--+--+ . | + * | SME |---. . | + * +-----+ \ . | + * . \ (llsd) +-----+ | + * . `-------->| SM | | + * . +--+--+ | + * . | | + * . +-----+ (llsd) | + * . | RSC |<--------' + * . +-----+ + * . | + * . +-----+ + * . | CP |--> HTTP PUT + * . +-----+ + * . . + * . . + * + * + * Key: + * + * SRE - Set Region Enqueued. Enqueue a 'Set Region' command in + * the other thread providing the new UUID of the region. + * TFReqSetRegion carries the data. + * SR - Set Region. New region UUID is sent to the thread-local + * collector. + * SME - Send Metrics Enqueued. Enqueue a 'Send Metrics' command + * including an ownership transfer of an LLSD. + * TFReqSendMetrics carries the data. + * SM - Send Metrics. Global metrics reporting operation. Takes + * the remote LLSD from the command, merges it with and LLSD + * from the local collector and sends it to the grid. + * AM - Agent Moved. Agent has completed some sort of move to a + * new region. + * TE - Timer Expired. Metrics timer has expired (on the order + * of 10 minutes). + * CP - CURL Put + * MSC - Modify Stats Collector. State change in the thread-local + * collector. Typically a region change which affects the + * global pointers used to find the 'current stats'. + * RSC - Read Stats Collector. Extract collector data in LLSD form. + * + */ +class TFRequest // : public LLQueuedThread::QueuedRequest +{ +public: + // Default ctors and assignment operator are correct. + + virtual ~TFRequest() + {} + + virtual bool doWork(LLTextureFetchWorker * worker) = 0; +}; + + +/** + * @brief Implements a 'Set Region' cross-thread command. + * + * When an agent moves to a new region, subsequent metrics need + * to be binned into a new or existing stats collection in 1:1 + * relationship with the region. We communicate this region + * change across the threads involved in the communication with + * this message. + * + * Corresponds to LLTextureFetch::commandSetRegion() + */ +class TFReqSetRegion : public TFRequest +{ +public: + TFReqSetRegion(const LLUUID & region_id) + : TFRequest(), + mRegionID(region_id) + {} + TFReqSetRegion & operator=(const TFReqSetRegion &); // Not defined + + virtual ~TFReqSetRegion() + {} + + virtual bool doWork(LLTextureFetchWorker * worker); + +public: + const LLUUID mRegionID; +}; + + +/** + * @brief Implements a 'Send Metrics' cross-thread command. + * + * This is the big operation. The main thread gathers metrics + * for a period of minutes into LLViewerAssetStats and other + * objects then builds an LLSD to represent the data. It uses + * this command to transfer the LLSD, content *and* ownership, + * to the TextureFetch thread which adds its own metrics and + * kicks of an HTTP POST of the resulting data to the currently + * active metrics collector. + * + * Corresponds to LLTextureFetch::commandSendMetrics() + */ +class TFReqSendMetrics : public TFRequest +{ +public: + /** + * Construct the 'Send Metrics' command to have the TextureFetch + * thread add and log metrics data. + * + * @param caps_url URL of a "ViewerMetrics" Caps target + * to receive the data. Does not have to + * be associated with a particular region. + * + * @param report_main Pointer to LLSD containing main + * thread metrics. Ownership transfers + * to the new thread using very carefully + * constructed code. + */ + TFReqSendMetrics(const std::string & caps_url, + LLSD * report_main) + : TFRequest(), + mCapsURL(caps_url), + mReportMain(report_main) + {} + TFReqSendMetrics & operator=(const TFReqSendMetrics &); // Not defined + + virtual ~TFReqSendMetrics(); + + virtual bool doWork(LLTextureFetchWorker * worker); + +public: + const std::string mCapsURL; + LLSD * mReportMain; +}; + +} // end of anonymous namespace + + ////////////////////////////////////////////////////////////////////////////// //static @@ -374,6 +586,9 @@ const char* LLTextureFetchWorker::sStateDescs[] = { "DONE", }; +// static +volatile bool LLTextureFetch::svMetricsDataBreak(true); // Start with a data break + // called from MAIN THREAD LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, @@ -423,7 +638,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mFirstPacket(0), mLastPacket(-1), mTotalPackets(0), - mImageCodec(IMG_CODEC_INVALID) + mImageCodec(IMG_CODEC_INVALID), + mMetricsStartTime(0) { mCanUseNET = mUrl.empty() ; @@ -591,6 +807,10 @@ bool LLTextureFetchWorker::doWork(S32 param) return true; // abort } } + + // Run a cross-thread command, if any. + mFetcher->cmdDoWork(this); + if(mImagePriority < F_ALMOST_ZERO) { if (mState == INIT || mState == LOAD_FROM_NETWORK || mState == LOAD_FROM_SIMULATOR) @@ -800,7 +1020,15 @@ bool LLTextureFetchWorker::doWork(S32 param) mRequestedDiscard = mDesiredDiscard; mSentRequest = QUEUED; mFetcher->addToNetworkQueue(this); + if (! mMetricsStartTime) + { + mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); + } + LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE, + false, + LLImageBase::TYPE_AVATAR_BAKE == mType); setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + return false; } else @@ -809,6 +1037,12 @@ bool LLTextureFetchWorker::doWork(S32 param) //llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end()); // Make certain this is in the network queue //mFetcher->addToNetworkQueue(this); + //if (! mMetricsStartTime) + //{ + // mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); + //} + //LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE, false, + // LLImageBase::TYPE_AVATAR_BAKE == mType); //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return false; } @@ -832,11 +1066,30 @@ bool LLTextureFetchWorker::doWork(S32 param) } setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); mState = DECODE_IMAGE; - mWriteToCacheState = SHOULD_WRITE ; + mWriteToCacheState = SHOULD_WRITE; + + if (mMetricsStartTime) + { + LLViewerAssetStatsFF::record_response_thread1(LLViewerAssetType::AT_TEXTURE, + false, + LLImageBase::TYPE_AVATAR_BAKE == mType, + LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime); + mMetricsStartTime = 0; + } + LLViewerAssetStatsFF::record_dequeue_thread1(LLViewerAssetType::AT_TEXTURE, + false, + LLImageBase::TYPE_AVATAR_BAKE == mType); } else { mFetcher->addToNetworkQueue(this); // failsafe + if (! mMetricsStartTime) + { + mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); + } + LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE, + false, + LLImageBase::TYPE_AVATAR_BAKE == mType); setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); } return false; @@ -898,6 +1151,14 @@ bool LLTextureFetchWorker::doWork(S32 param) mState = WAIT_HTTP_REQ; mFetcher->addToHTTPQueue(mID); + if (! mMetricsStartTime) + { + mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); + } + LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE, + true, + LLImageBase::TYPE_AVATAR_BAKE == mType); + // Will call callbackHttpGet when curl request completes std::vector headers; headers.push_back("Accept: image/x-j2c"); @@ -1534,6 +1795,12 @@ LLTextureFetch::~LLTextureFetch() { clearDeleteList() ; + while (! mCommands.empty()) + { + delete mCommands.front(); + mCommands.erase(mCommands.begin()); + } + // ~LLQueuedThread() called here } @@ -1815,6 +2082,25 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) return res; } +// virtual +bool LLTextureFetch::runCondition() +{ + // Caller is holding the lock on LLThread's condition variable. + + // LLQueuedThread, unlike its base class LLThread, makes this a + // private method which is unfortunate. I want to use it directly + // but I'm going to have to re-implement the logic here (or change + // declarations, which I don't want to do right now). + + bool have_no_commands(false); + { + LLMutexLock lock(&mQueueMutex); + + have_no_commands = mCommands.empty(); + } + return ! (have_no_commands && mRequestQueue.empty() && mIdleThread); +} + ////////////////////////////////////////////////////////////////////////////// // MAIN THREAD @@ -2357,3 +2643,195 @@ void LLTextureFetch::dump() } } +////////////////////////////////////////////////////////////////////////////// + +// cross-thread command methods + +void LLTextureFetch::commandSetRegion(const LLUUID & region_id) +{ + TFReqSetRegion * req = new TFReqSetRegion(region_id); + + cmdEnqueue(req); +} + +void LLTextureFetch::commandSendMetrics(const std::string & caps_url, + LLSD * report_main) +{ + TFReqSendMetrics * req = new TFReqSendMetrics(caps_url, report_main); + + cmdEnqueue(req); +} + +void LLTextureFetch::commandDataBreak() +{ + // The pedantically correct way to implement this is to create a command + // request object in the above fashion and enqueue it. However, this is + // simple data of an advisorial not operational nature and this case + // of shared-write access is tolerable. + + LLTextureFetch::svMetricsDataBreak = true; +} + +void LLTextureFetch::cmdEnqueue(TFRequest * req) +{ + lockQueue(); + mCommands.push_back(req); + wake(); + unlockQueue(); +} + +TFRequest * LLTextureFetch::cmdDequeue() +{ + TFRequest * ret = 0; + + lockQueue(); + if (! mCommands.empty()) + { + ret = mCommands.front(); + mCommands.erase(mCommands.begin()); + } + unlockQueue(); + + return ret; +} + +void LLTextureFetch::cmdDoWork(LLTextureFetchWorker * worker) +{ + // Queue is expected to be locked here. + + if (mDebugPause) + { + return; // debug: don't do any work + } + + TFRequest * req = cmdDequeue(); + if (req) + { + // One request per pass should really be enough for this. + req->doWork(worker); + delete req; + } +} + + +////////////////////////////////////////////////////////////////////////////// + +// Private (anonymous) class methods implementing the command scheme. + +namespace +{ + +/** + * Implements the 'Set Region' command. + * + * Thread: Thread1 (TextureFetch) + */ +bool +TFReqSetRegion::doWork(LLTextureFetchWorker *) +{ + LLViewerAssetStatsFF::set_region_thread1(mRegionID); + + return true; +} + + +TFReqSendMetrics::~TFReqSendMetrics() +{ + delete mReportMain; + mReportMain = 0; +} + + +/** + * Implements the 'Send Metrics' command. Takes over + * ownership of the passed LLSD pointer. + * + * Thread: Thread1 (TextureFetch) + */ +bool +TFReqSendMetrics::doWork(LLTextureFetchWorker * fetch_worker) +{ + /* + * HTTP POST responder. Doesn't do much but tries to + * detect simple breaks in recording the metrics stream. + * + * The 'volatile' modifiers don't indicate signals, + * mmap'd memory or threads, really. They indicate that + * the referenced data is part of a pseudo-closure for + * this responder rather than being required for correct + * operation. + */ + class lcl_responder : public LLCurl::Responder + { + public: + lcl_responder(volatile bool & post_failed, + volatile bool & post_succeeded) + : LLHTTPClient::Responder(), + mPostFailedStatus(post_failed), + mPostSucceededStatus(post_succeeded) + {} + + // virtual + void error(U32 status_num, const std::string & reason) + { + mPostFailedStatus = true; + } + + // virtual + void result(const LLSD & content) + { + mPostSucceededStatus = true; + } + + private: + volatile bool & mPostFailedStatus; + volatile bool & mPostSucceededStatus; + }; + + if (! gViewerAssetStatsThread1) + return true; + + if (! mCapsURL.empty()) + { + static volatile bool not_initial_report(false); + static S32 report_sequence(0); + + // We've already taken over ownership of the LLSD at this point + // and can do normal LLSD sharing operations at this point. But + // still being careful, regardless. + LLSD & envelope = *mReportMain; + { + envelope["sequence"] = report_sequence; + envelope["regions_alt"] = gViewerAssetStatsThread1->asLLSD(); + envelope["initial"] = ! not_initial_report; // Initial data from viewer + envelope["break"] = LLTextureFetch::svMetricsDataBreak; // Break in data prior to this report + + // *FIXME: Need to merge the two metrics streams here.... + } + + // Update sequence number and other metadata for next attempt. + if (S32_MAX == ++report_sequence) + report_sequence = 0; + LLTextureFetch::svMetricsDataBreak = false; + + LLCurlRequest::headers_t headers; + fetch_worker->getFetcher().getCurlRequest().post(mCapsURL, + headers, + envelope, + new lcl_responder(LLTextureFetch::svMetricsDataBreak, + not_initial_report)); + } + else + { + LLTextureFetch::svMetricsDataBreak = true; + } + + gViewerAssetStatsThread1->reset(); + + return true; +} + +} // end of anonymous namespace + + + diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 796109df06..220305d881 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -40,6 +40,7 @@ class HTTPGetResponder; class LLTextureCache; class LLImageDecodeThread; class LLHost; +namespace { class TFRequest; } // Interface class class LLTextureFetch : public LLWorkerThread @@ -83,6 +84,13 @@ public: LLTextureFetchWorker* getWorkerAfterLock(const LLUUID& id); LLTextureInfo* getTextureInfo() { return &mTextureInfo; } + + // Commands available to other threads. + void commandSetRegion(const LLUUID & region_id); + void commandSendMetrics(const std::string & caps_url, LLSD * report_main); + void commandDataBreak(); + + LLCurlRequest & getCurlRequest() { return *mCurlGetRequest; } protected: void addToNetworkQueue(LLTextureFetchWorker* worker); @@ -91,7 +99,10 @@ protected: void removeFromHTTPQueue(const LLUUID& id, S32 received_size = 0); void removeRequest(LLTextureFetchWorker* worker, bool cancel); // Called from worker thread (during doWork) - void processCurlRequests(); + void processCurlRequests(); + + // Overrides from the LLThread tree + bool runCondition(); private: void sendRequestListToSimulators(); @@ -99,6 +110,11 @@ private: /*virtual*/ void endThread(void); /*virtual*/ void threadedUpdate(void); + // command helpers + void cmdEnqueue(TFRequest *); + TFRequest * cmdDequeue(); + void cmdDoWork(LLTextureFetchWorker* worker); + public: LLUUID mDebugID; S32 mDebugCount; @@ -107,7 +123,7 @@ public: S32 mBadPacketCount; private: - LLMutex mQueueMutex; //to protect mRequestMap only + LLMutex mQueueMutex; //to protect mRequestMap and mCommands only LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue. LLTextureCache* mTextureCache; @@ -129,6 +145,19 @@ private: LLTextureInfo mTextureInfo; U32 mHTTPTextureBits; + + // Special cross-thread command queue. This command queue + // is logically tied to LLQueuedThread's list of + // QueuedRequest instances and so must be covered by the + // same locks. + typedef std::vector command_queue_t; + command_queue_t mCommands; + +public: + // A probabilistically-correct indicator that the current + // attempt to log metrics follows a break in the metrics stream + // reporting due to either startup or a problem POSTing data. + static volatile bool svMetricsDataBreak; }; #endif // LL_LLTEXTUREFETCH_H diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index 37e7c43f36..09c0364f09 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -37,6 +37,35 @@ #include "stdtypes.h" /* + * Classes and utility functions for per-thread and per-region + * asset and experiential metrics to be aggregated grid-wide. + * + * The basic metrics grouping is LLViewerAssetStats::PerRegionStats. + * This provides various counters and simple statistics for asset + * fetches binned into a few categories. One of these is maintained + * for each region encountered and the 'current' region is available + * as a simple reference. Each thread (presently two) interested + * in participating in these stats gets an instance of the + * LLViewerAssetStats class so that threads are completely + * independent. + * + * The idea of a current region is used for simplicity and speed + * of categorization. Each metrics event could have taken a + * region uuid argument resulting in a suitable lookup. Arguments + * against this design include: + * + * - Region uuid not trivially available to caller. + * - Cost (cpu, disruption in real work flow) too high. + * - Additional precision not really meaningful. + * + * By itself, the LLViewerAssetStats class is thread- and + * viewer-agnostic and can be used anywhere without assumptions + * of global pointers and other context. For the viewer, + * a set of free functions are provided in the namespace + * LLViewerAssetStatsFF which *do* implement viewer-native + * policies about per-thread globals and will do correct + * defensive tests of same. + * * References * * Project: @@ -103,7 +132,7 @@ LLViewerAssetStats::reset() mRegionStats.clear(); // If we have a current stats, reset it, otherwise, as at construction, - // create a new one. + // create a new one as we must always have a current stats block. if (mCurRegionStats) { mCurRegionStats->reset(); @@ -130,7 +159,7 @@ LLViewerAssetStats::setRegionID(const LLUUID & region_id) PerRegionContainer::iterator new_stats = mRegionStats.find(region_id); if (mRegionStats.end() == new_stats) { - // Haven't seen this region_id before, create a new block make it current. + // Haven't seen this region_id before, create a new block and make it current. mCurRegionStats = new PerRegionStats(region_id); mRegionStats[region_id] = mCurRegionStats; } @@ -159,7 +188,7 @@ LLViewerAssetStats::recordGetDequeued(LLViewerAssetType::EType at, bool with_htt } void -LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration) +LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, duration_t duration) { const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); @@ -213,9 +242,9 @@ LLViewerAssetStats::asLLSD() const slot[enq_tag] = LLSD(S32(stats.mRequests[i].mEnqueued.getCount())); slot[deq_tag] = LLSD(S32(stats.mRequests[i].mDequeued.getCount())); slot[rcnt_tag] = LLSD(S32(stats.mRequests[i].mResponse.getCount())); - slot[rmin_tag] = LLSD(stats.mRequests[i].mResponse.getMin()); - slot[rmax_tag] = LLSD(stats.mRequests[i].mResponse.getMax()); - slot[rmean_tag] = LLSD(stats.mRequests[i].mResponse.getMean()); + slot[rmin_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMin())); + slot[rmax_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMax())); + slot[rmean_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMean())); } ret[it->first.asString()] = reg_stat; @@ -231,9 +260,24 @@ LLViewerAssetStats::asLLSD() const namespace LLViewerAssetStatsFF { +// // Target thread is elaborated in the function name. This could // have been something 'templatey' like specializations iterated // over a set of constants but with so few, this is clearer I think. +// +// As for the threads themselves... rather than do fine-grained +// locking as we gather statistics, this code creates a collector +// for each thread, allocated and run independently. Logging +// happens at relatively infrequent intervals and at that time +// the data is sent to a single thread to be aggregated into +// a single entity with locks, thread safety and other niceties. +// +// A particularly fussy implementation would distribute the +// per-thread pointers across separate cache lines. But that should +// be beyond current requirements. +// + +// 'main' thread - initial program thread void set_region_main(const LLUUID & region_id) @@ -263,7 +307,7 @@ record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp) } void -record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration) +record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration) { if (! gViewerAssetStatsMain) return; @@ -272,6 +316,8 @@ record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, } +// 'thread1' - should be for TextureFetch thread + void set_region_thread1(const LLUUID & region_id) { @@ -300,7 +346,7 @@ record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp } void -record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration) +record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration) { if (! gViewerAssetStatsThread1) return; @@ -308,6 +354,31 @@ record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_tem gViewerAssetStatsThread1->recordGetServiced(at, with_http, is_temp, duration); } + +void +init() +{ + if (! gViewerAssetStatsMain) + { + gViewerAssetStatsMain = new LLViewerAssetStats; + } + if (! gViewerAssetStatsThread1) + { + gViewerAssetStatsThread1 = new LLViewerAssetStats; + } +} + +void +cleanup() +{ + delete gViewerAssetStatsMain; + gViewerAssetStatsMain = 0; + + delete gViewerAssetStatsThread1; + gViewerAssetStatsThread1 = 0; +} + + } // namespace LLViewerAssetStatsFF diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index b8356a5ff5..efd0897bb8 100644 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -95,6 +95,13 @@ public: EVACCount // Must be last }; + /** + * Type for duration and other time values in the metrics. Selected + * for compatibility with the pre-existing timestamp on the texture + * fetcher class, LLTextureFetch. + */ + typedef U64 duration_t; + /** * Collected data for a single region visited by the avatar. */ @@ -107,6 +114,7 @@ public: { reset(); } + // Default assignment and destructor are correct. void reset(); @@ -114,9 +122,9 @@ public: LLUUID mRegionID; struct { - LLSimpleStatCounter mEnqueued; - LLSimpleStatCounter mDequeued; - LLSimpleStatMMM<> mResponse; + LLSimpleStatCounter mEnqueued; + LLSimpleStatCounter mDequeued; + LLSimpleStatMMM mResponse; } mRequests [EVACCount]; }; @@ -137,7 +145,7 @@ public: // Non-Cached GET Requests void recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp); void recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp); - void recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration); + void recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, duration_t duration); // Retrieve current metrics for all visited regions. const LLSD asLLSD() const; @@ -180,23 +188,51 @@ extern LLViewerAssetStats * gViewerAssetStatsThread1; namespace LLViewerAssetStatsFF { +/** + * We have many timers, clocks etc. in the runtime. This is the + * canonical timestamp for these metrics which is compatible with + * the pre-existing timestamping in the texture fetcher. + */ +inline LLViewerAssetStats::duration_t get_timestamp() +{ + return LLTimer::getTotalTime(); +} +/** + * Region context, event and duration loggers for the Main thread. + */ void set_region_main(const LLUUID & region_id); void record_enqueue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp); void record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp); -void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration); +void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, + LLViewerAssetStats::duration_t duration); +/** + * Region context, event and duration loggers for Thread 1. + */ void set_region_thread1(const LLUUID & region_id); void record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp); void record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp); -void record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, F64 duration); +void record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, + LLViewerAssetStats::duration_t duration); + +/** + * @brief Allocation and deallocation of globals. + * + * init() should be called before threads are started that will access it though + * you'll likely get away with calling it afterwards. cleanup() should only be + * called after threads are shutdown to prevent races on the global pointers. + */ +void init(); + +void cleanup(); } // namespace LLViewerAssetStatsFF diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 2e7ef0fec3..197cb3468c 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -33,6 +33,61 @@ #include "message.h" #include "llagent.h" +#include "lltransfersourceasset.h" +#include "lltransfertargetvfile.h" +#include "llviewerassetstats.h" + +///---------------------------------------------------------------------------- +/// LLViewerAssetRequest +///---------------------------------------------------------------------------- + +/** + * @brief Local class to encapsulate asset fetch requests with a timestamp. + * + * Derived from the common LLAssetRequest class, this is currently used + * only for fetch/get operations and its only function is to wrap remote + * asset fetch requests so that they can be timed. + */ +class LLViewerAssetRequest : public LLAssetRequest +{ +public: + LLViewerAssetRequest(const LLUUID &uuid, const LLAssetType::EType type) + : LLAssetRequest(uuid, type), + mMetricsStartTime(0) + { + } + + LLViewerAssetRequest & operator=(const LLViewerAssetRequest &); // Not defined + // Default assignment operator valid + + // virtual + ~LLViewerAssetRequest() + { + recordMetrics(); + } + +protected: + void recordMetrics() + { + if (mMetricsStartTime) + { + // Okay, it appears this request was used for useful things. Record + // the expected dequeue and duration of request processing. + LLViewerAssetStatsFF::record_dequeue_main(mType, false, false); + LLViewerAssetStatsFF::record_response_main(mType, false, false, + (LLViewerAssetStatsFF::get_timestamp() + - mMetricsStartTime)); + mMetricsStartTime = 0; + } + } + +public: + LLViewerAssetStats::duration_t mMetricsStartTime; +}; + +///---------------------------------------------------------------------------- +/// LLViewerAssetStorage +///---------------------------------------------------------------------------- LLViewerAssetStorage::LLViewerAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs, LLVFS *static_vfs, @@ -258,3 +313,72 @@ void LLViewerAssetStorage::storeAssetData( } } } + + +/** + * @brief Allocate and queue an asset fetch request for the viewer + * + * This is a nearly-verbatim copy of the base class's implementation + * with the following changes: + * - Use a locally-derived request class + * - Start timing for metrics when request is queued + * + * This is an unfortunate implementation choice but it's forced by + * current conditions. A refactoring that might clean up the layers + * of responsibility or introduce factories or more virtualization + * of methods would enable a more attractive solution. + * + * If LLAssetStorage::_queueDataRequest changes, this must change + * as well. + */ + +// virtual +void LLViewerAssetStorage::_queueDataRequest( + const LLUUID& uuid, + LLAssetType::EType atype, + LLGetAssetCallback callback, + void *user_data, + BOOL duplicate, + BOOL is_priority) +{ + if (mUpstreamHost.isOk()) + { + // stash the callback info so we can find it after we get the response message + LLViewerAssetRequest *req = new LLViewerAssetRequest(uuid, atype); + req->mDownCallback = callback; + req->mUserData = user_data; + req->mIsPriority = is_priority; + req->mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); + + mPendingDownloads.push_back(req); + + if (!duplicate) + { + // send request message to our upstream data provider + // Create a new asset transfer. + LLTransferSourceParamsAsset spa; + spa.setAsset(uuid, atype); + + // Set our destination file, and the completion callback. + LLTransferTargetParamsVFile tpvf; + tpvf.setAsset(uuid, atype); + tpvf.setCallback(downloadCompleteCallback, req); + + llinfos << "Starting transfer for " << uuid << llendl; + LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET); + ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f)); + + LLViewerAssetStatsFF::record_enqueue_main(atype, false, false); + } + } + else + { + // uh-oh, we shouldn't have gotten here + llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl; + if (callback) + { + callback(mVFS, uuid, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM); + } + } +} + diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index 6346b79f03..ca9b9943fa 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -63,6 +63,17 @@ public: bool is_priority = false, bool user_waiting=FALSE, F64 timeout=LL_ASSET_STORAGE_TIMEOUT); + +protected: + using LLAssetStorage::_queueDataRequest; + + // virtual + void _queueDataRequest(const LLUUID& uuid, + LLAssetType::EType type, + void (*callback) (LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), + void *user_data, + BOOL duplicate, + BOOL is_priority); }; #endif diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 98f16757b2..79b45a459f 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1403,6 +1403,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url) capabilityNames.append("UpdateNotecardTaskInventory"); capabilityNames.append("UpdateScriptTask"); capabilityNames.append("UploadBakedTexture"); + capabilityNames.append("ViewerMetrics"); capabilityNames.append("ViewerStartAuction"); capabilityNames.append("ViewerStats"); capabilityNames.append("WebFetchInventoryDescendents"); diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index affe16c177..c3c38ef925 100644 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -114,7 +114,7 @@ namespace tut LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_response_main(LLViewerAssetType::AT_GESTURE, false, false, 12.3); + LLViewerAssetStatsFF::record_response_main(LLViewerAssetType::AT_GESTURE, false, false, 12300000ULL); } // Create a non-global instance and check the structure -- cgit v1.2.3 From 359ed16947445d04abd1d15ef7225f5852e3fe09 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 18 Nov 2010 11:22:32 -0800 Subject: STORM-151 : Modified install.py to point to the new kdu 6.4.1 and changed kdu lib name for windows --- indra/cmake/LLKDU.cmake | 2 +- install.xml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/indra/cmake/LLKDU.cmake b/indra/cmake/LLKDU.cmake index 0c103e89d2..5b28f9b2e6 100644 --- a/indra/cmake/LLKDU.cmake +++ b/indra/cmake/LLKDU.cmake @@ -10,7 +10,7 @@ endif (INSTALL_PROPRIETARY AND NOT STANDALONE) if (USE_KDU) use_prebuilt_binary(kdu) if (WINDOWS) - set(KDU_LIBRARY debug kdu_cored optimized kdu_core) + set(KDU_LIBRARY debug kdud optimized kdu) else (WINDOWS) set(KDU_LIBRARY kdu) endif (WINDOWS) diff --git a/install.xml b/install.xml index db148f1c61..0f25d34327 100644 --- a/install.xml +++ b/install.xml @@ -830,16 +830,16 @@ darwin md5sum - 3b40e7170dea82c1443e8d90cd44a13d + 14b1d25d7c59e42ed545f7c9f180496a url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-4.2.1-darwin-20080926.tar.bz2 + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-6.4.1-darwin-20101117.tar.bz2 linux md5sum - a6d2f0995c25d7f53bd12b8ec0d6b462 + ea0862a349ca56324348913fe7ef365b url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-4.2.1-linux-20080930.tar.bz2 + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-6.4.1-linux-20101118.tar.bz2 linux64 @@ -851,9 +851,9 @@ windows md5sum - 1b9f61140f8b599cdae5e00d21dbb177 + d4c4ddb68f20f1712335c209ca0d66dd url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-4.2.1-windows-20080926.tar.bz2 + scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-6.4.1-windows-20101117.tar.bz2 -- cgit v1.2.3 From 9682b9b5db695643b90720f9da2c8d03e4559dd4 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 18 Nov 2010 15:26:49 -0800 Subject: STORM-151 : suppress the linux64 ref in install.xml and attempt to fix llkdumem.cpp linux compile issue --- indra/llkdu/llkdumem.cpp | 2 +- install.xml | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/indra/llkdu/llkdumem.cpp b/indra/llkdu/llkdumem.cpp index 811c5b52bb..300b8e28af 100644 --- a/indra/llkdu/llkdumem.cpp +++ b/indra/llkdu/llkdumem.cpp @@ -390,4 +390,4 @@ void LLKDUMemOut::put(int comp_idx, kdu_line_buf &line, int x_tnum) free_lines = scan; } } -*/ \ No newline at end of file +*/ diff --git a/install.xml b/install.xml index 0f25d34327..c1eec2efbf 100644 --- a/install.xml +++ b/install.xml @@ -841,13 +841,6 @@ url scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-6.4.1-linux-20101118.tar.bz2 - linux64 - - md5sum - f4e2e2b3440594527729a8c85119e508 - url - scp:install-packages.lindenlab.com:/local/www/install-packages/doc/kdu-5.2.1-linux64-20080926.tar.bz2 - windows md5sum -- cgit v1.2.3 From ffa6d31707cea8de8b3853c23ff4a4fc07b65d60 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Thu, 18 Nov 2010 17:39:21 -0800 Subject: EXP-411 FIX Underlined text looks bad on OSX (almost strikethrough) Changing the way the Qt library embedded in llqtwebkit is built solves this issue. It's now being built against the 10.5 SDK, and configured to use the Cocoa rendering path. --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index 8bdfc424b7..47ca70dbfa 100644 --- a/install.xml +++ b/install.xml @@ -981,9 +981,9 @@ anguage Infrstructure (CLI) international standard darwin md5sum - 2a272816119ff5da1712ad7a49fc9c51 + f95677e8cfcdac9d9e41766b869727a9 url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-darwin-qt4.7.1-20101116.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-darwin-qt4.7.1-20101118.tar.bz2 linux -- cgit v1.2.3 From a927b1cb0e0454cacf9523d2be7f2ce4b19c9e04 Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Thu, 18 Nov 2010 22:34:54 -0800 Subject: SOCIAL-266 WIP HTTP AUTH dialogs no longer work in LLQtWebKit 4.7.1 initial support for XUI auth dialog --- indra/llui/llnotifications.cpp | 11 +++- indra/llui/llnotifications.h | 1 + indra/llui/llnotificationtemplate.h | 14 ++--- indra/newview/llbrowsernotification.cpp | 2 +- indra/newview/llmediactrl.cpp | 63 +++++++++++++++++----- indra/newview/llmediactrl.h | 4 +- indra/newview/llviewermedia.cpp | 6 +-- .../newview/skins/default/xui/en/notifications.xml | 45 +++++++++++----- 8 files changed, 105 insertions(+), 41 deletions(-) diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index a3df6a3ced..15edf270bd 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -81,6 +81,7 @@ LLNotificationForm::FormButton::FormButton() LLNotificationForm::FormInput::FormInput() : type("type"), + text("text"), max_length_chars("max_length_chars"), width("width", 0), value("value") @@ -404,7 +405,7 @@ LLNotificationTemplate::LLNotificationTemplate(const LLNotificationTemplate::Par it != end_it; ++it) { - mUniqueContext.push_back(it->key); + mUniqueContext.push_back(it->value); } mForm = LLNotificationFormPtr(new LLNotificationForm(p.name, p.form_ref.form)); @@ -719,13 +720,19 @@ bool LLNotification::isEquivalentTo(LLNotificationPtr that) const { const LLSD& these_substitutions = this->getSubstitutions(); const LLSD& those_substitutions = that->getSubstitutions(); + const LLSD& this_payload = this->getPayload(); + const LLSD& that_payload = that->getPayload(); // highlander bit sez there can only be one of these for (std::vector::const_iterator it = mTemplatep->mUniqueContext.begin(), end_it = mTemplatep->mUniqueContext.end(); it != end_it; ++it) { - if (these_substitutions.get(*it).asString() != those_substitutions.get(*it).asString()) + // if templates differ in either substitution strings or payload with the given field name + // then they are considered inequivalent + // use of get() avoids converting the LLSD value to a map as the [] operator would + if (these_substitutions.get(*it).asString() != those_substitutions.get(*it).asString() + || this_payload.get(*it).asString() != that_payload.get(*it).asString()) { return false; } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 524cff70e8..a607f52b97 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -195,6 +195,7 @@ public: Mandatory type; Optional width; Optional max_length_chars; + Optional text; Optional value; FormInput(); diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index 6bc0d2aaff..644d5c4d74 100644 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -74,11 +74,13 @@ struct LLNotificationTemplate struct UniquenessContext : public LLInitParam::Block { - Mandatory key; + Mandatory value; UniquenessContext() - : key("key") - {} + : value("value") + { + addSynonym(value, "key"); + } }; @@ -88,7 +90,7 @@ struct LLNotificationTemplate // this idiom allows // // as well as - // ... + // ... Optional dummy_val; public: Multiple contexts; @@ -232,8 +234,8 @@ struct LLNotificationTemplate // (used for things like progress indications, or repeating warnings // like "the grid is going down in N minutes") bool mUnique; - // if we want to be unique only if a certain part of the payload is constant - // specify the field names for the payload. The notification will only be + // if we want to be unique only if a certain part of the payload or substitutions args + // are constant specify the field names for the payload. The notification will only be // combined if all of the fields named in the context are identical in the // new and the old notification; otherwise, the notification will be // duplicated. This is to support suppressing duplicate offers from the same diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index d6a813d608..633ef4f1ce 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -29,8 +29,8 @@ #include "llnotificationhandler.h" #include "llnotifications.h" -#include "llfloaterreg.h" #include "llmediactrl.h" +#include "llviewermedia.h" using namespace LLNotificationsUI; diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 0a5263d1ab..edfc039036 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -54,6 +54,7 @@ #include "llbutton.h" #include "llcheckboxctrl.h" #include "llnotifications.h" +#include "lllineeditor.h" extern BOOL gRestoreGL; @@ -69,7 +70,6 @@ LLMediaCtrl::Params::Params() texture_height("texture_height", 1024), caret_color("caret_color"), initial_mime_type("initial_mime_type"), - media_id("media_id"), trusted_content("trusted_content", false) { tab_stop(false); @@ -126,7 +126,7 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : setTextureSize(screen_width, screen_height); } - mMediaTextureID.generate(); + mMediaTextureID = getKey(); // We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to. if(!mHomePageUrl.empty()) @@ -140,8 +140,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : // addChild( mBorder ); } -//////////////////////////////////////////////////////////////////////////////// -// note: this is now a singleton and destruction happens via initClass() now LLMediaCtrl::~LLMediaCtrl() { @@ -1037,7 +1035,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LLNotification::Params notify_params; notify_params.name = "PopupAttempt"; - notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", getKey()); + notify_params.payload = LLSD().with("target", target).with("url", url).with("uuid", uuid).with("media_id", mMediaTextureID); notify_params.functor.function = boost::bind(&LLMediaCtrl::onPopup, this, _1, _2); if (mTrusted) @@ -1095,8 +1093,12 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) case MEDIA_EVENT_AUTH_REQUEST: { - LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() << ", realm " << self->getAuthRealm() << LL_ENDL; - } + LLNotification::Params auth_request_params; + auth_request_params.name = "AuthRequest"; + auth_request_params.payload = LLSD().with("media_id", mMediaTextureID); + auth_request_params.functor.function = boost::bind(&LLMediaCtrl::onAuthSubmit, this, _1, _2); + LLNotifications::instance().add(auth_request_params); + }; break; }; @@ -1122,9 +1124,21 @@ void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) // Make sure the opening instance knows its window open request was denied, so it can clean things up. LLViewerMedia::proxyWindowClosed(notification["payload"]["uuid"]); } +} +void LLMediaCtrl::onAuthSubmit(const LLSD& notification, const LLSD& response) +{ + if (response["ok"]) + { + mMediaSource->getMediaPlugin()->sendAuthResponse(true, response["username"], response["password"]); + } + else + { + mMediaSource->getMediaPlugin()->sendAuthResponse(false, "", ""); + } } + void LLMediaCtrl::onCloseNotification() { LLNotifications::instance().cancel(mCurNotification); @@ -1145,15 +1159,20 @@ void LLMediaCtrl::onClickNotificationButton(const std::string& name) { if (!mCurNotification) return; - LLSD response = mCurNotification->getResponseTemplate(); - response[name] = true; + mCurNotificationResponse[name] = true; - mCurNotification->respond(response); + mCurNotification->respond(mCurNotificationResponse); +} + +void LLMediaCtrl::onEnterNotificationText(LLUICtrl* ctrl, const std::string& name) +{ + mCurNotificationResponse[name] = ctrl->getValue().asString(); } void LLMediaCtrl::showNotification(LLNotificationPtr notify) { mCurNotification = notify; + mCurNotificationResponse = notify->getResponseTemplate(); // add popup here LLSD payload = notify->getPayload(); @@ -1206,12 +1225,30 @@ void LLMediaCtrl::showNotification(LLNotificationPtr notify) cur_x = button->getRect().mRight + FORM_PADDING_HORIZONTAL; } + else if (form_element["type"].asString() == "text") + { + LLTextBox::Params label_p; + label_p.name = form_element["name"].asString() + "_label"; + label_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x + 120, FORM_PADDING_VERTICAL); + label_p.initial_value = form_element["text"]; + LLTextBox* textbox = LLUICtrlFactory::create(label_p); + textbox->reshapeToFitText(); + form_elements.addChild(textbox); + cur_x = textbox->getRect().mRight + FORM_PADDING_HORIZONTAL; + + LLLineEditor::Params line_p; + line_p.name = form_element["name"]; + line_p.commit_callback.function = boost::bind(&LLMediaCtrl::onEnterNotificationText, this, _1, form_element["name"].asString()); + line_p.commit_on_focus_lost = true; + line_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x + 120, FORM_PADDING_VERTICAL); + + LLLineEditor* line_editor = LLUICtrlFactory::create(line_p); + form_elements.addChild(line_editor); + cur_x = line_editor->getRect().mRight + FORM_PADDING_HORIZONTAL; + } } - form_elements.reshape(cur_x, form_elements.getRect().getHeight()); - - //LLWeb::loadURL(payload["url"], payload["target"]); } void LLMediaCtrl::hideNotification() diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 65dfbbff78..5b18099c76 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -61,7 +61,6 @@ public: Optional caret_color; Optional initial_mime_type; - Optional media_id; Params(); }; @@ -167,8 +166,10 @@ public: private: void onVisibilityChange ( const LLSD& new_visibility ); void onPopup(const LLSD& notification, const LLSD& response); + void onAuthSubmit(const LLSD& notification, const LLSD& response); void onCloseNotification(); void onClickNotificationButton(const std::string& name); + void onEnterNotificationText(LLUICtrl* ctrl, const std::string& name); void onClickIgnore(LLUICtrl* ctrl); const S32 mTextureDepthBytes; @@ -194,6 +195,7 @@ public: S32 mTextureHeight; bool mClearCache; boost::shared_ptr mCurNotification; + LLSD mCurNotificationResponse; }; #endif // LL_LLMediaCtrl_H diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index bcac6533e6..9df4ba2ea2 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2903,7 +2903,6 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla LL_DEBUGS("Media") << "MEDIA_EVENT_CLICK_LINK_NOFOLLOW, uri is: " << plugin->getClickURL() << LL_ENDL; std::string url = plugin->getClickURL(); LLURLDispatcher::dispatch(url, NULL, mTrustedBrowser); - } break; case MEDIA_EVENT_CLICK_LINK_HREF: @@ -3060,10 +3059,9 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST: { llinfos << "MEDIA_EVENT_AUTH_REQUEST, url " << plugin->getAuthURL() << ", realm " << plugin->getAuthRealm() << LL_ENDL; - - // TODO: open an auth dialog that will call this when complete - plugin->sendAuthResponse(false, "", ""); + //plugin->sendAuthResponse(false, "", ""); } + break; case LLViewerMediaObserver::MEDIA_EVENT_CLOSE_REQUEST: { diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index a0fd0a13cc..190418e384 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4983,7 +4983,7 @@ If you want to view streaming media on parcels that support it you should go to type="notify"> No Media Plugin was found to handle the "[MIME_TYPE]" mime type. Media of this type will be unavailable. - + MIME_TYPE @@ -5885,7 +5885,7 @@ You may only select up to [MAX_SELECT] items from this list. [NAME] is inviting you to a Voice Chat call. Click Accept to join the call or Decline to decline the invitation. Click Block to block this caller. - + NAME
+ + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 4f982cc8e9..2f47d4e201 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -182,6 +182,13 @@ function="Advanced.WebBrowserTest" parameter="http://join.secondlife.com/"/> + + + - + + + Date: Wed, 1 Dec 2010 14:42:12 -0800 Subject: download progress events. --- indra/newview/llappviewer.cpp | 1 - .../updater/llupdatedownloader.cpp | 44 ++++++++++++++++++++++ indra/viewer_components/updater/llupdaterservice.h | 3 +- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b6f52e3e15..aa20ff55b6 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2402,7 +2402,6 @@ namespace { LLNotificationsUtil::add("FailedUpdateInstall"); break; default: - llinfos << "unhandled update event " << evt << llendl; break; } diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index c17a50e242..7b0f960ce4 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -29,6 +29,7 @@ #include #include #include "lldir.h" +#include "llevents.h" #include "llfile.h" #include "llmd5.h" #include "llsd.h" @@ -49,6 +50,7 @@ public: bool isDownloading(void); size_t onHeader(void * header, size_t size); size_t onBody(void * header, size_t size); + int onProgress(double downloadSize, double bytesDownloaded); void resume(void); private: @@ -57,6 +59,7 @@ private: CURL * mCurl; LLSD mDownloadData; llofstream mDownloadStream; + unsigned char mDownloadPercent; std::string mDownloadRecordPath; curl_slist * mHeaderList; @@ -149,6 +152,17 @@ namespace { size_t bytes = blockSize * blocks; return reinterpret_cast(downloader)->onHeader(data, bytes); } + + + int progress_callback(void * downloader, + double dowloadTotal, + double downloadNow, + double uploadTotal, + double uploadNow) + { + return reinterpret_cast(downloader)-> + onProgress(dowloadTotal, downloadNow); + } } @@ -157,6 +171,7 @@ LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & mCancelled(false), mClient(client), mCurl(0), + mDownloadPercent(0), mHeaderList(0) { CURLcode code = curl_global_init(CURL_GLOBAL_ALL); // Just in case. @@ -290,6 +305,30 @@ size_t LLUpdateDownloader::Implementation::onBody(void * buffer, size_t size) } +int LLUpdateDownloader::Implementation::onProgress(double downloadSize, double bytesDownloaded) +{ + int downloadPercent = static_cast(100. * (bytesDownloaded / downloadSize)); + if(downloadPercent > mDownloadPercent) { + mDownloadPercent = downloadPercent; + + LLSD event; + event["pump"] = LLUpdaterService::pumpName(); + LLSD payload; + payload["type"] = LLSD(LLUpdaterService::PROGRESS); + payload["download_size"] = downloadSize; + payload["bytes_downloaded"] = bytesDownloaded; + event["payload"] = payload; + LLEventPumps::instance().obtain("mainlooprepeater").post(event); + + LL_INFOS("UpdateDownload") << "progress event " << payload << LL_ENDL; + } else { + ; // Keep events to a reasonalbe number. + } + + return 0; +} + + void LLUpdateDownloader::Implementation::run(void) { CURLcode code = curl_easy_perform(mCurl); @@ -343,6 +382,11 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u } throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_HTTPGET, true)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str())); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, &progress_callback)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSDATA, this)); + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOPROGRESS, false)); + + mDownloadPercent = 0; } diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 752a6f834b..1266bcae08 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -48,7 +48,8 @@ public: INVALID, DOWNLOAD_COMPLETE, DOWNLOAD_ERROR, - INSTALL_ERROR + INSTALL_ERROR, + PROGRESS }; LLUpdaterService(); -- cgit v1.2.3 From 765d939956a0c1f67029d44fd29770aabc36d9b4 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Wed, 1 Dec 2010 15:51:10 -0800 Subject: state change events for updater service. --- .../viewer_components/updater/llupdaterservice.cpp | 62 +++++++++++++++++++++- indra/viewer_components/updater/llupdaterservice.h | 16 +++++- 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index cc60eaead2..cfda314d43 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -98,6 +98,8 @@ class LLUpdaterServiceImpl : LLUpdaterService::app_exit_callback_t mAppExitCallback; + LLUpdaterService::eUpdaterState mState; + LOG_CLASS(LLUpdaterServiceImpl); public: @@ -115,6 +117,7 @@ public: void startChecking(bool install_if_ready); void stopChecking(); bool isChecking(); + LLUpdaterService::eUpdaterState getState(); void setAppExitCallback(LLUpdaterService::app_exit_callback_t aecb) { mAppExitCallback = aecb;} @@ -139,6 +142,7 @@ public: private: void restartTimer(unsigned int seconds); + void setState(LLUpdaterService::eUpdaterState state); void stopTimer(); }; @@ -149,7 +153,8 @@ LLUpdaterServiceImpl::LLUpdaterServiceImpl() : mIsDownloading(false), mCheckPeriod(0), mUpdateChecker(*this), - mUpdateDownloader(*this) + mUpdateDownloader(*this), + mState(LLUpdaterService::INITIAL) { } @@ -201,10 +206,16 @@ void LLUpdaterServiceImpl::startChecking(bool install_if_ready) if(!mIsDownloading) { + setState(LLUpdaterService::CHECKING_FOR_UPDATE); + // Checking can only occur during the mainloop. // reset the timer to 0 so that the next mainloop event // triggers a check; restartTimer(0); + } + else + { + setState(LLUpdaterService::DOWNLOADING); } } } @@ -222,6 +233,8 @@ void LLUpdaterServiceImpl::stopChecking() mUpdateDownloader.cancel(); mIsDownloading = false; } + + setState(LLUpdaterService::TERMINAL); } bool LLUpdaterServiceImpl::isChecking() @@ -229,6 +242,11 @@ bool LLUpdaterServiceImpl::isChecking() return mIsChecking; } +LLUpdaterService::eUpdaterState LLUpdaterServiceImpl::getState() +{ + return mState; +} + bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller) { bool foundInstall = false; // return true if install is found. @@ -266,6 +284,8 @@ bool LLUpdaterServiceImpl::checkForInstall(bool launchInstaller) { if(launchInstaller) { + setState(LLUpdaterService::INSTALLING); + LLFile::remove(update_marker_path()); int result = ll_install_update(install_script_path(), @@ -335,6 +355,8 @@ void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion, stopTimer(); mIsDownloading = true; mUpdateDownloader.download(uri, hash); + + setState(LLUpdaterService::DOWNLOADING); } void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion, @@ -344,6 +366,8 @@ void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion, stopTimer(); mIsDownloading = true; mUpdateDownloader.download(uri, hash); + + setState(LLUpdaterService::DOWNLOADING); } void LLUpdaterServiceImpl::upToDate(void) @@ -352,6 +376,8 @@ void LLUpdaterServiceImpl::upToDate(void) { restartTimer(mCheckPeriod); } + + setState(LLUpdaterService::UP_TO_DATE); } void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) @@ -369,6 +395,8 @@ void LLUpdaterServiceImpl::downloadComplete(LLSD const & data) payload["type"] = LLSD(LLUpdaterService::DOWNLOAD_COMPLETE); event["payload"] = payload; LLEventPumps::instance().obtain("mainlooprepeater").post(event); + + setState(LLUpdaterService::TERMINAL); } void LLUpdaterServiceImpl::downloadError(std::string const & message) @@ -390,6 +418,8 @@ void LLUpdaterServiceImpl::downloadError(std::string const & message) payload["message"] = message; event["payload"] = payload; LLEventPumps::instance().obtain("mainlooprepeater").post(event); + + setState(LLUpdaterService::ERROR); } void LLUpdaterServiceImpl::restartTimer(unsigned int seconds) @@ -402,6 +432,28 @@ void LLUpdaterServiceImpl::restartTimer(unsigned int seconds) sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1)); } +void LLUpdaterServiceImpl::setState(LLUpdaterService::eUpdaterState state) +{ + if(state != mState) + { + mState = state; + + LLSD event; + event["pump"] = LLUpdaterService::pumpName(); + LLSD payload; + payload["type"] = LLSD(LLUpdaterService::STATE_CHANGE); + payload["state"] = state; + event["payload"] = payload; + LLEventPumps::instance().obtain("mainlooprepeater").post(event); + + LL_INFOS("UpdaterService") << "setting state to " << state << LL_ENDL; + } + else + { + ; // State unchanged; noop. + } +} + void LLUpdaterServiceImpl::stopTimer() { mTimer.stop(); @@ -425,10 +477,13 @@ bool LLUpdaterServiceImpl::onMainLoop(LLSD const & event) LLSD event; event["type"] = LLSD(LLUpdaterService::INSTALL_ERROR); LLEventPumps::instance().obtain(LLUpdaterService::pumpName()).post(event); + + setState(LLUpdaterService::TERMINAL); } else { mUpdateChecker.check(mProtocolVersion, mUrl, mPath, mChannel, mVersion); + setState(LLUpdaterService::CHECKING_FOR_UPDATE); } } else @@ -496,6 +551,11 @@ bool LLUpdaterService::isChecking() return mImpl->isChecking(); } +LLUpdaterService::eUpdaterState LLUpdaterService::getState() +{ + return mImpl->getState(); +} + void LLUpdaterService::setImplAppExitCallback(LLUpdaterService::app_exit_callback_t aecb) { return mImpl->setAppExitCallback(aecb); diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 1266bcae08..6ee7060d28 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -44,12 +44,23 @@ public: static std::string const & pumpName(void); // Type codes for events posted by this service. Stored the event's 'type' element. - enum eUpdateEvent { + enum eUpdaterEvent { INVALID, DOWNLOAD_COMPLETE, DOWNLOAD_ERROR, INSTALL_ERROR, - PROGRESS + PROGRESS, + STATE_CHANGE + }; + + enum eUpdaterState { + INITIAL, + CHECKING_FOR_UPDATE, + DOWNLOADING, + INSTALLING, + UP_TO_DATE, + TERMINAL, + ERROR }; LLUpdaterService(); @@ -66,6 +77,7 @@ public: void startChecking(bool install_if_ready = false); void stopChecking(); bool isChecking(); + eUpdaterState getState(); typedef boost::function app_exit_callback_t; template -- cgit v1.2.3 From a2420db5b3b2ed216bcb3f08fce95a05ee7e6dd5 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Wed, 1 Dec 2010 16:40:40 -0800 Subject: SOCIAL-249 FIX pressing any of the Alt keys and 0-9 will output the number and symbol instead of just symbol The issue seems to be Mac-only, so I've put the fix inside #if LL_DARWIN. Windows' handling of ALT is very different, so the fix might not be appropriate there. --- indra/llplugin/llpluginclassmedia.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 61d779b98d..e514b5abbe 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -522,7 +522,15 @@ bool LLPluginClassMedia::keyEvent(EKeyEventType type, int key_code, MASK modifie } break; } - + +#if LL_DARWIN + if(modifiers & MASK_ALT) + { + // Option-key modified characters should be handled by the unicode input path instead of this one. + result = false; + } +#endif + if(result) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "key_event"); -- cgit v1.2.3 From 880110eb9303ecb4426e6d3598075c4c12280061 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Wed, 1 Dec 2010 18:15:59 -0800 Subject: OCIAL-231 FIX Enable tooltips (for links and images) Added the necessary plumbing to get link_hovered events from the webkit plugin through to the viewer UI. This requires a llqtwebkit library built from revision 1799a899e06d or later in http://hg.secondlife.com/llqtwebkit to function. The viewer source changes are backwards-compatible with earlier versions of llqtwebkit, it just won't see any link_hovered events with previous revisions. Reviewed by Callum. --- indra/llplugin/llpluginclassmedia.cpp | 9 ++++ indra/llplugin/llpluginclassmedia.h | 4 ++ indra/llplugin/llpluginclassmediaowner.h | 4 +- indra/media_plugins/webkit/media_plugin_webkit.cpp | 14 +++++++ indra/newview/llmediactrl.cpp | 48 +++++++++++++++++++++- indra/newview/llmediactrl.h | 2 + indra/newview/llviewerparcelmedia.cpp | 6 +++ indra/test_apps/llplugintest/llmediaplugintest.cpp | 6 +++ 8 files changed, 90 insertions(+), 3 deletions(-) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index e514b5abbe..de4456aa4e 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -1047,6 +1047,15 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE); } + else if(message_name == "link_hovered") + { + // Link and text are not currently used -- the tooltip hover text is taken from the "title". + // message.getValue("link"); + mHoverText = message.getValue("title"); + // message.getValue("text"); + + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED); + } else { LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 3720455431..fa4dc2b43f 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -242,6 +242,9 @@ public: std::string getAuthURL() const { return mAuthURL; }; std::string getAuthRealm() const { return mAuthRealm; }; + // This is valid during MEDIA_EVENT_LINK_HOVERED + std::string getHoverText() const { return mHoverText; }; + std::string getMediaName() const { return mMediaName; }; std::string getMediaDescription() const { return mMediaDescription; }; @@ -381,6 +384,7 @@ protected: S32 mGeometryHeight; std::string mAuthURL; std::string mAuthRealm; + std::string mHoverText; ///////////////////////////////////////// // media_time class diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h index 42a89baebc..42e93cc6d7 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -61,7 +61,9 @@ public: MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch MEDIA_EVENT_PLUGIN_FAILED, // The plugin died unexpectedly - MEDIA_EVENT_AUTH_REQUEST // The plugin wants to display an auth dialog + MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog + + MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin } EMediaEvent; diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 8b70c15b27..1666f877e9 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -605,6 +605,20 @@ private: mAuthPassword = message.getValue("password"); } } + + //////////////////////////////////////////////////////////////////////////////// + // virtual + void onLinkHovered(const EventType& event) + { + if(mInitState >= INIT_STATE_NAVIGATE_COMPLETE) + { + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "link_hovered"); + message.setValue("link", event.getEventUri()); + message.setValue("title", event.getStringValue()); + message.setValue("text", event.getStringValue2()); + sendMessage(message); + } + } LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers) { diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 54c7d361b7..08d07f9540 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -25,7 +25,7 @@ */ #include "llviewerprecompiledheaders.h" - +#include "lltooltip.h" #include "llmediactrl.h" @@ -351,7 +351,8 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : mClearCache(false), mHomePageMimeType(p.initial_mime_type), mTrusted(p.trusted_content), - mWindowShade(NULL) + mWindowShade(NULL), + mHoverTextChanged(false) { { LLColor4 color = p.caret_color().get(); @@ -433,6 +434,13 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask ) mMediaSource->mouseMove(x, y, mask); gViewerWindow->setCursor(mMediaSource->getLastSetCursor()); } + + // TODO: Is this the right way to handle hover text changes driven by the plugin? + if(mHoverTextChanged) + { + mHoverTextChanged = false; + handleToolTip(x, y, mask); + } return TRUE; } @@ -448,6 +456,35 @@ BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks ) return TRUE; } +//////////////////////////////////////////////////////////////////////////////// +// virtual +BOOL LLMediaCtrl::handleToolTip(S32 x, S32 y, MASK mask) +{ + std::string hover_text; + + if (mMediaSource && mMediaSource->hasMedia()) + hover_text = mMediaSource->getMediaPlugin()->getHoverText(); + + if(hover_text.empty()) + { + return FALSE; + } + else + { + S32 screen_x, screen_y; + + localPointToScreen(x, y, &screen_x, &screen_y); + LLRect sticky_rect_screen; + sticky_rect_screen.setCenterAndSize(screen_x, screen_y, 20, 20); + + LLToolTipMgr::instance().show(LLToolTip::Params() + .message(hover_text) + .sticky_rect(sticky_rect_screen)); + } + + return TRUE; +} + //////////////////////////////////////////////////////////////////////////////// // BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) @@ -1270,6 +1307,13 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LLNotifications::instance().add(auth_request_params); }; break; + + case MEDIA_EVENT_LINK_HOVERED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL; + mHoverTextChanged = true; + }; + break; }; // chain all events to any potential observers of this object. diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index efb94fa1c1..0c369840bf 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -88,6 +88,7 @@ public: virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); + virtual BOOL handleToolTip(S32 x, S32 y, MASK mask); // navigation void navigateTo( std::string url_in, std::string mime_type = ""); @@ -191,6 +192,7 @@ public: S32 mTextureHeight; bool mClearCache; class LLWindowShade* mWindowShade; + bool mHoverTextChanged; }; #endif // LL_LLMediaCtrl_H diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 41e59c626d..40f0b43313 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -592,6 +592,12 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() << ", realm " << self->getAuthRealm() << LL_ENDL; } break; + + case MEDIA_EVENT_LINK_HOVERED: + { + LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << LL_ENDL; + }; + break; }; } diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index f2a10bc264..f8483225d9 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -2229,6 +2229,12 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e self->sendAuthResponse(false, "", ""); } break; + + case MEDIA_EVENT_LINK_HOVERED: + { + std::cerr << "Media event: MEDIA_EVENT_LINK_HOVERED, hover text is: " << self->getHoverText() << std::endl; + }; + break; } } -- cgit v1.2.3 From 3f2f03923cc2789dc85d09fabfd19c7e92e7bfa9 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Wed, 1 Dec 2010 18:23:46 -0800 Subject: SOCIAL-231 FIX Enable tooltips (for links and images) New build of mac llqtwebkit library from revision 1799a899e06d in http://hg.secondlife.com/llqtwebkit . --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index 1ab4895426..1055aba3e2 100644 --- a/install.xml +++ b/install.xml @@ -981,9 +981,9 @@ anguage Infrstructure (CLI) international standard darwin md5sum - ab0bf1a14702d5ddc8c3af1d15f7d6c3 + c69208572a74df24e910e419fbbbb884 url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-darwin-qt4.7.1-20101122.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-darwin-qt4.7.1-20101201.tar.bz2 linux -- cgit v1.2.3 From 88eabbd0776ed0c2ce923b23cda14b9f91445aa4 Mon Sep 17 00:00:00 2001 From: callum Date: Wed, 1 Dec 2010 19:02:53 -0800 Subject: SOCIAL-311 PARTIAL FIX (2) Media browser has too many oddities to be useful for viewer web apps Latest traunch of fixes to new Web only content floater Also removed line in test app that fails to build - have a note to fix later --- indra/media_plugins/webkit/media_plugin_webkit.cpp | 4 +- indra/newview/app_settings/settings.xml | 13 +- indra/newview/llfloaterwebcontent.cpp | 585 +++++++++++---------- indra/newview/llfloaterwebcontent.h | 148 +++--- .../skins/default/xui/en/floater_web_content.xml | 275 +++++----- indra/test_apps/llplugintest/llmediaplugintest.cpp | 2 +- install.xml | 4 +- 7 files changed, 555 insertions(+), 476 deletions(-) diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 1666f877e9..19244d2d1f 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -407,6 +407,8 @@ private: { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_begin"); message.setValue("uri", event.getEventUri()); + message.setValueBoolean("history_back_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_BACK)); + message.setValueBoolean("history_forward_available", LLQtWebKit::getInstance()->userActionIsEnabled( mBrowserWindowId, LLQtWebKit::UA_NAVIGATE_FORWARD)); sendMessage(message); setStatus(STATUS_LOADING); @@ -605,7 +607,7 @@ private: mAuthPassword = message.getValue("password"); } } - + //////////////////////////////////////////////////////////////////////////////// // virtual void onLinkHovered(const EventType& event) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index ef45eaa1db..5548abc623 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -6626,7 +6626,18 @@ MediaBrowserWindowLimit Comment - Maximum number of media brower windows that can be open at once (0 for no limit) + Maximum number of media brower windows that can be open at once in the media browser floater (0 for no limit) + Persist + 1 + Type + S32 + Value + 5 + + WebContentWindowLimit + + Comment + Maximum number of web brower windows that can be open at once in the Web content floater (0 for no limit) Persist 1 Type diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 138ddeabda..8321b2914f 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -1,276 +1,309 @@ -/** - * @file llfloaterwebcontent.cpp - * @brief floater for displaying web content - e.g. profiles and search (eventually) - * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloaterwebcontent.h" - -#include "llfloaterreg.h" -#include "llparcel.h" -#include "llpluginclassmedia.h" -#include "lluictrlfactory.h" -#include "llmediactrl.h" -#include "llviewerwindow.h" -#include "llviewercontrol.h" -#include "llviewerparcelmgr.h" -#include "llweb.h" -#include "llui.h" -#include "roles_constants.h" - -#include "llurlhistory.h" -#include "llviewermedia.h" -#include "llviewerparcelmedia.h" -#include "llcombobox.h" -#include "llwindow.h" -#include "lllayoutstack.h" -#include "llcheckboxctrl.h" - -#include "llnotifications.h" - -// TEMP -#include "llsdutil.h" - -LLFloaterWebContent::LLFloaterWebContent(const LLSD& key) - : LLFloater(key) -{ -} - -//static -void LLFloaterWebContent::create(const std::string &url, const std::string& target, const std::string& uuid) -{ - lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl; - - std::string tag = target; - - if(target.empty() || target == "_blank") - { - if(!uuid.empty()) - { - tag = uuid; - } - else - { - // create a unique tag for this instance - LLUUID id; - id.generate(); - tag = id.asString(); - } - } - - S32 browser_window_limit = gSavedSettings.getS32("MediaBrowserWindowLimit"); - - if(LLFloaterReg::findInstance("web_content", tag) != NULL) - { - // There's already a web browser for this tag, so we won't be opening a new window. - } - else if(browser_window_limit != 0) - { - // showInstance will open a new window. Figure out how many web browsers are already open, - // and close the least recently opened one if this will put us over the limit. - - LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("web_content"); - lldebugs << "total instance count is " << instances.size() << llendl; - - for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++) - { - lldebugs << " " << (*iter)->getKey() << llendl; - } - - if(instances.size() >= (size_t)browser_window_limit) - { - // Destroy the least recently opened instance - (*instances.begin())->closeFloater(); - } - } - - LLFloaterWebContent *browser = dynamic_cast (LLFloaterReg::showInstance("web_content", tag)); - llassert(browser); - if(browser) - { - browser->mUUID = uuid; - - // tell the browser instance to load the specified URL - browser->openMedia(url, target); - LLViewerMedia::proxyWindowOpened(target, uuid); - } -} - -//static -void LLFloaterWebContent::closeRequest(const std::string &uuid) -{ - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); - lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) - { - LLFloaterWebContent* i = dynamic_cast(*iter); - lldebugs << " " << i->mUUID << llendl; - if (i && i->mUUID == uuid) - { - i->closeFloater(false); - return; - } - } -} - -//static -void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height) -{ - LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); - lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; - for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) - { - LLFloaterWebContent* i = dynamic_cast(*iter); - lldebugs << " " << i->mUUID << llendl; - if (i && i->mUUID == uuid) - { - i->geometryChanged(x, y, width, height); - return; - } - } -} - -void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) -{ - // Make sure the layout of the browser control is updated, so this calculation is correct. - LLLayoutStack::updateClass(); - - // TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc. - LLCoordWindow window_size; - getWindow()->getSize(&window_size); - - // Adjust width and height for the size of the chrome on the web Browser window. - width += getRect().getWidth() - mWebBrowser->getRect().getWidth(); - height += getRect().getHeight() - mWebBrowser->getRect().getHeight(); - - LLRect geom; - geom.setOriginAndSize(x, window_size.mY - (y + height), width, height); - - lldebugs << "geometry change: " << geom << llendl; - - handleReshape(geom,false); -} - -void LLFloaterWebContent::openMedia(const std::string& web_url, const std::string& target) -{ - mWebBrowser->setHomePageUrl(web_url); - mWebBrowser->setTarget(target); - mWebBrowser->navigateTo(web_url); - setCurrentURL(web_url); -} - -void LLFloaterWebContent::draw() -{ -// getChildView("go")->setEnabled(!mAddressCombo->getValue().asString().empty()); - - getChildView("back")->setEnabled(mWebBrowser->canNavigateBack()); - getChildView("forward")->setEnabled(mWebBrowser->canNavigateForward()); - - LLFloater::draw(); -} - -BOOL LLFloaterWebContent::postBuild() -{ - mWebBrowser = getChild("webbrowser"); - mWebBrowser->addObserver(this); - - childSetAction("back", onClickBack, this); - childSetAction("forward", onClickForward, this); - childSetAction("reload", onClickRefresh, this); - childSetAction("go", onClickGo, this); - - return TRUE; -} - -//virtual -void LLFloaterWebContent::onClose(bool app_quitting) -{ - LLViewerMedia::proxyWindowClosed(mUUID); - destroy(); -} - -void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) -{ - if(event == MEDIA_EVENT_LOCATION_CHANGED) - { - setCurrentURL(self->getLocation()); - } - else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) - { - // This is the event these flags are sent with. - getChildView("back")->setEnabled(self->getHistoryBackAvailable()); - getChildView("forward")->setEnabled(self->getHistoryForwardAvailable()); - } - else if(event == MEDIA_EVENT_CLOSE_REQUEST) - { - // The browser instance wants its window closed. - closeFloater(); - } - else if(event == MEDIA_EVENT_GEOMETRY_CHANGE) - { - geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight()); - } -} - -void LLFloaterWebContent::setCurrentURL(const std::string& url) -{ - mCurrentURL = url; - - getChildView("back")->setEnabled(mWebBrowser->canNavigateBack()); - getChildView("forward")->setEnabled(mWebBrowser->canNavigateForward()); - getChildView("reload")->setEnabled(TRUE); -} - -//static -void LLFloaterWebContent::onClickRefresh(void* user_data) -{ - LLFloaterWebContent* self = (LLFloaterWebContent*)user_data; - - self->mWebBrowser->navigateTo(self->mCurrentURL); -} - -//static -void LLFloaterWebContent::onClickForward(void* user_data) -{ - LLFloaterWebContent* self = (LLFloaterWebContent*)user_data; - - self->mWebBrowser->navigateForward(); -} - -//static -void LLFloaterWebContent::onClickBack(void* user_data) -{ - LLFloaterWebContent* self = (LLFloaterWebContent*)user_data; - - self->mWebBrowser->navigateBack(); -} - -//static -void LLFloaterWebContent::onClickGo(void* user_data) -{ -// LLFloaterWebContent* self = (LLFloaterWebContent*)user_data; - -// self->mWebBrowser->navigateTo(self->mAddressCombo->getValue().asString()); -} +/** + * @file llfloaterwebcontent.cpp + * @brief floater for displaying web content - e.g. profiles and search (eventually) + * + * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llcombobox.h" +#include "llfloaterreg.h" +#include "lllayoutstack.h" +#include "llpluginclassmedia.h" +#include "llprogressbar.h" +#include "lltextbox.h" +#include "llviewercontrol.h" +#include "llwindow.h" + +#include "llfloaterwebcontent.h" + +LLFloaterWebContent::LLFloaterWebContent(const LLSD& key) + : LLFloater(key) +{ + mCommitCallbackRegistrar.add("WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this)); + mCommitCallbackRegistrar.add("WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this)); + mCommitCallbackRegistrar.add("WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this)); + + mCommitCallbackRegistrar.add("WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this)); + mCommitCallbackRegistrar.add("WebContent.Go", boost::bind( &LLFloaterWebContent::onClickGo, this)); +} + +BOOL LLFloaterWebContent::postBuild() +{ + // these are used in a bunch of places so cache them + mWebBrowser = getChild("webbrowser"); + mAddressCombo = getChild("address"); + mStatusBarText = getChild("statusbartext"); + mStatusBarProgress = getChild("statusbarprogress"); + + // observe browser events + mWebBrowser->addObserver(this); + + // these button are always enabled + getChildView("reload")->setEnabled( true ); + getChildView("go")->setEnabled( true ); + + return TRUE; +} + +//static +void LLFloaterWebContent::create(const std::string &url, const std::string& target, const std::string& uuid) +{ + lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl; + + std::string tag = target; + + if(target.empty() || target == "_blank") + { + if(!uuid.empty()) + { + tag = uuid; + } + else + { + // create a unique tag for this instance + LLUUID id; + id.generate(); + tag = id.asString(); + } + } + + S32 browser_window_limit = gSavedSettings.getS32("WebContentWindowLimit"); + + if(LLFloaterReg::findInstance("web_content", tag) != NULL) + { + // There's already a web browser for this tag, so we won't be opening a new window. + } + else if(browser_window_limit != 0) + { + // showInstance will open a new window. Figure out how many web browsers are already open, + // and close the least recently opened one if this will put us over the limit. + + LLFloaterReg::const_instance_list_t &instances = LLFloaterReg::getFloaterList("web_content"); + lldebugs << "total instance count is " << instances.size() << llendl; + + for(LLFloaterReg::const_instance_list_t::const_iterator iter = instances.begin(); iter != instances.end(); iter++) + { + lldebugs << " " << (*iter)->getKey() << llendl; + } + + if(instances.size() >= (size_t)browser_window_limit) + { + // Destroy the least recently opened instance + (*instances.begin())->closeFloater(); + } + } + + LLFloaterWebContent *browser = dynamic_cast (LLFloaterReg::showInstance("web_content", tag)); + llassert(browser); + if(browser) + { + browser->mUUID = uuid; + + // tell the browser instance to load the specified URL + browser->open_media(url, target); + LLViewerMedia::proxyWindowOpened(target, uuid); + } +} + +//static +void LLFloaterWebContent::closeRequest(const std::string &uuid) +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); + lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) + { + LLFloaterWebContent* i = dynamic_cast(*iter); + lldebugs << " " << i->mUUID << llendl; + if (i && i->mUUID == uuid) + { + i->closeFloater(false); + return; + } + } +} + +//static +void LLFloaterWebContent::geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height) +{ + LLFloaterReg::const_instance_list_t& inst_list = LLFloaterReg::getFloaterList("web_content"); + lldebugs << "instance list size is " << inst_list.size() << ", incoming uuid is " << uuid << llendl; + for (LLFloaterReg::const_instance_list_t::const_iterator iter = inst_list.begin(); iter != inst_list.end(); ++iter) + { + LLFloaterWebContent* i = dynamic_cast(*iter); + lldebugs << " " << i->mUUID << llendl; + if (i && i->mUUID == uuid) + { + i->geometryChanged(x, y, width, height); + return; + } + } +} + +void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) +{ + // Make sure the layout of the browser control is updated, so this calculation is correct. + LLLayoutStack::updateClass(); + + // TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc. + LLCoordWindow window_size; + getWindow()->getSize(&window_size); + + // Adjust width and height for the size of the chrome on the web Browser window. + width += getRect().getWidth() - mWebBrowser->getRect().getWidth(); + height += getRect().getHeight() - mWebBrowser->getRect().getHeight(); + + LLRect geom; + geom.setOriginAndSize(x, window_size.mY - (y + height), width, height); + + lldebugs << "geometry change: " << geom << llendl; + + handleReshape(geom,false); +} + +void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target) +{ + mWebBrowser->setHomePageUrl(web_url); + mWebBrowser->setTarget(target); + mWebBrowser->navigateTo(web_url); + set_current_url(web_url); +} + +//virtual +void LLFloaterWebContent::onClose(bool app_quitting) +{ + LLViewerMedia::proxyWindowClosed(mUUID); + destroy(); +} + +void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) +{ + if(event == MEDIA_EVENT_LOCATION_CHANGED) + { + const std::string url = self->getStatusText(); + + if ( url.length() ) + mStatusBarText->setText( url ); + + set_current_url( url ); + } + else if(event == MEDIA_EVENT_NAVIGATE_BEGIN) + { + // flags are sent with this event + getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); + getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); + + // manually decide on the state of this button + getChildView("stop")->setEnabled( true ); + + // turn "on" progress bar now we're loaded + mStatusBarProgress->setVisible( true ); + } + else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) + { + // flags are sent with this event + getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); + getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); + + // manually decide on the state of this button + getChildView("stop")->setEnabled( false ); + + // turn "off" progress bar now we're loaded + mStatusBarProgress->setVisible( false ); + } + else if(event == MEDIA_EVENT_CLOSE_REQUEST) + { + // The browser instance wants its window closed. + closeFloater(); + } + else if(event == MEDIA_EVENT_GEOMETRY_CHANGE) + { + geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight()); + } + else if(event == MEDIA_EVENT_STATUS_TEXT_CHANGED ) + { + const std::string text = self->getStatusText(); + if ( text.length() ) + mStatusBarText->setText( text ); + } + else if(event == MEDIA_EVENT_PROGRESS_UPDATED ) + { + int percent = (int)self->getProgressPercent(); + mStatusBarProgress->setPercent( percent ); + } + else if(event == MEDIA_EVENT_NAME_CHANGED ) + { + std::string page_title = self->getMediaName(); + setTitle( page_title ); + } +} + +void LLFloaterWebContent::set_current_url(const std::string& url) +{ + mCurrentURL = url; + + // redirects will navigate momentarily to about:blank, don't add to history + if ( mCurrentURL != "about:blank" ) + { + mAddressCombo->remove( mCurrentURL ); + mAddressCombo->add( mCurrentURL ); + mAddressCombo->selectByValue( mCurrentURL ); + } +} + +void LLFloaterWebContent::onClickForward() +{ + mWebBrowser->navigateForward(); +} + +void LLFloaterWebContent::onClickBack() +{ + mWebBrowser->navigateBack(); +} + +void LLFloaterWebContent::onClickReload() +{ + mAddressCombo->remove(0); + + if( mWebBrowser->getMediaPlugin() ) + { + bool ignore_cache = true; + mWebBrowser->getMediaPlugin()->browse_reload( ignore_cache ); + }; +} + +void LLFloaterWebContent::onClickStop() +{ + if( mWebBrowser->getMediaPlugin() ) + mWebBrowser->getMediaPlugin()->stop(); +} + +void LLFloaterWebContent::onEnterAddress() +{ + mWebBrowser->navigateTo( mAddressCombo->getValue().asString() ); +} + +void LLFloaterWebContent::onClickGo() +{ + mWebBrowser->navigateTo( mAddressCombo->getValue().asString() ); +} diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 71346aa80e..b41da57a6f 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -1,71 +1,77 @@ -/** - * @file llfloaterwebcontent.h - * @brief floater for displaying web content - e.g. profiles and search (eventually) - * - * $LicenseInfo:firstyear=2006&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_LLFLOATERWEBCONTENT_H -#define LL_LLFLOATERWEBCONTENT_H - -#include "llfloater.h" -#include "llmediactrl.h" - -class LLMediaCtrl; - -class LLFloaterWebContent : - public LLFloater, - public LLViewerMediaObserver -{ -public: - LOG_CLASS(LLFloaterWebContent); - LLFloaterWebContent(const LLSD& key); - - static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null); - - static void closeRequest(const std::string &uuid); - static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height); - void geometryChanged(S32 x, S32 y, S32 width, S32 height); - - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ void draw(); - - // inherited from LLViewerMediaObserver - /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); - - void openMedia(const std::string& media_url, const std::string& target); - void setCurrentURL(const std::string& url); - - static void onClickRefresh(void* user_data); - static void onClickBack(void* user_data); - static void onClickForward(void* user_data); - static void onClickGo(void* user_data); - -private: - LLMediaCtrl* mWebBrowser; - std::string mCurrentURL; - std::string mUUID; -}; - -#endif // LL_LLFLOATERWEBCONTENT_H - +/** + * @file llfloaterwebcontent.h + * @brief floater for displaying web content - e.g. profiles and search (eventually) + * + * $LicenseInfo:firstyear=2006&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_LLFLOATERWEBCONTENT_H +#define LL_LLFLOATERWEBCONTENT_H + +#include "llfloater.h" +#include "llmediactrl.h" + +class LLMediaCtrl; +class LLComboBox; +class LLTextBox; +class LLProgressBar; + +class LLFloaterWebContent : + public LLFloater, + public LLViewerMediaObserver +{ +public: + LOG_CLASS(LLFloaterWebContent); + LLFloaterWebContent(const LLSD& key); + + static void create(const std::string &url, const std::string& target, const std::string& uuid = LLStringUtil::null); + + static void closeRequest(const std::string &uuid); + static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height); + void geometryChanged(S32 x, S32 y, S32 width, S32 height); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_quitting); + + // inherited from LLViewerMediaObserver + /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); + + void onClickBack(); + void onClickForward(); + void onClickReload(); + void onClickStop(); + void onEnterAddress(); + void onClickGo(); + +private: + void open_media(const std::string& media_url, const std::string& target); + void set_current_url(const std::string& url); + + LLMediaCtrl* mWebBrowser; + LLComboBox* mAddressCombo; + LLTextBox* mStatusBarText; + LLProgressBar* mStatusBarProgress; + std::string mCurrentURL; + std::string mUUID; +}; + +#endif // LL_LLFLOATERWEBCONTENT_H diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index 777c67261a..62df206360 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -1,124 +1,151 @@ - - - - http://www.secondlife.com - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index f8483225d9..4a2272032b 100644 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -2223,7 +2223,7 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e case MEDIA_EVENT_AUTH_REQUEST: { - std::cerr << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() ", realm " << self->getAuthRealm() << std::endl; + //std::cerr << "Media event: MEDIA_EVENT_AUTH_REQUEST, url " << self->getAuthURL() ", realm " << self->getAuthRealm() << std::endl; // TODO: display an auth dialog self->sendAuthResponse(false, "", ""); diff --git a/install.xml b/install.xml index 1055aba3e2..2ad6b17675 100644 --- a/install.xml +++ b/install.xml @@ -995,9 +995,9 @@ anguage Infrstructure (CLI) international standard windows md5sum - eb048de70c366084e1abb4fbf0e71edf + 40ee8464da01fde6845b8276dcb4cc0f url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101129.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101201.tar.bz2 -- cgit v1.2.3 From adb62e958ff3a4be2eb43fbb1754358ec60a118c Mon Sep 17 00:00:00 2001 From: callum Date: Wed, 1 Dec 2010 22:25:13 -0800 Subject: SOCIAL-311 PARTIAL FIX Media browser has too many oddities to be useful for viewer web apps Added support for graphic browser buttons and laid them out differently --- indra/newview/llfloaterwebcontent.cpp | 13 +--- .../skins/default/xui/en/floater_web_content.xml | 88 +++++++++++----------- 2 files changed, 49 insertions(+), 52 deletions(-) diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 8321b2914f..8e5638f549 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -45,7 +45,6 @@ LLFloaterWebContent::LLFloaterWebContent(const LLSD& key) mCommitCallbackRegistrar.add("WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this)); mCommitCallbackRegistrar.add("WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this)); - mCommitCallbackRegistrar.add("WebContent.Go", boost::bind( &LLFloaterWebContent::onClickGo, this)); } BOOL LLFloaterWebContent::postBuild() @@ -61,7 +60,6 @@ BOOL LLFloaterWebContent::postBuild() // these button are always enabled getChildView("reload")->setEnabled( true ); - getChildView("go")->setEnabled( true ); return TRUE; } @@ -214,7 +212,8 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); // manually decide on the state of this button - getChildView("stop")->setEnabled( true ); + getChildView("reload")->setVisible( false ); + getChildView("stop")->setVisible( true ); // turn "on" progress bar now we're loaded mStatusBarProgress->setVisible( true ); @@ -226,7 +225,8 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); // manually decide on the state of this button - getChildView("stop")->setEnabled( false ); + getChildView("reload")->setVisible( true ); + getChildView("stop")->setVisible( false ); // turn "off" progress bar now we're loaded mStatusBarProgress->setVisible( false ); @@ -302,8 +302,3 @@ void LLFloaterWebContent::onEnterAddress() { mWebBrowser->navigateTo( mAddressCombo->getValue().asString() ); } - -void LLFloaterWebContent::onClickGo() -{ - mWebBrowser->navigateTo( mAddressCombo->getValue().asString() ); -} diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index 62df206360..97a7a0e737 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -24,7 +24,7 @@ + + width="729"> - + top="0"/> Date: Thu, 2 Dec 2010 11:37:26 -0800 Subject: expose update available method. --- indra/viewer_components/updater/llupdaterservice.cpp | 5 +++++ indra/viewer_components/updater/llupdaterservice.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index cfda314d43..92a0a09137 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -504,6 +504,11 @@ std::string const & LLUpdaterService::pumpName(void) return name; } +bool LLUpdaterService::updateReadyToInstall(void) +{ + return LLFile::isfile(update_marker_path()); +} + LLUpdaterService::LLUpdaterService() { if(gUpdater.expired()) diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 6ee7060d28..3763fbfde0 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -43,6 +43,9 @@ public: // Name of the event pump through which update events will be delivered. static std::string const & pumpName(void); + // Returns true if an update has been completely downloaded and is now ready to install. + static bool updateReadyToInstall(void); + // Type codes for events posted by this service. Stored the event's 'type' element. enum eUpdaterEvent { INVALID, -- cgit v1.2.3 From 2ea7b1a05e2fd773962bb6495148f900d6640b00 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 2 Dec 2010 14:05:21 -0800 Subject: STORM-151 : Remove files we have no use of --- indra/llkdu/llblockdata.cpp | 162 -------------------- indra/llkdu/llblockdata.h | 107 ------------- indra/llkdu/llblockdecoder.cpp | 270 -------------------------------- indra/llkdu/llblockdecoder.h | 42 ----- indra/llkdu/llblockencoder.cpp | 340 ----------------------------------------- indra/llkdu/llblockencoder.h | 49 ------ 6 files changed, 970 deletions(-) delete mode 100644 indra/llkdu/llblockdata.cpp delete mode 100644 indra/llkdu/llblockdata.h delete mode 100644 indra/llkdu/llblockdecoder.cpp delete mode 100644 indra/llkdu/llblockdecoder.h delete mode 100644 indra/llkdu/llblockencoder.cpp delete mode 100644 indra/llkdu/llblockencoder.h diff --git a/indra/llkdu/llblockdata.cpp b/indra/llkdu/llblockdata.cpp deleted file mode 100644 index 6a7bc3e6c4..0000000000 --- a/indra/llkdu/llblockdata.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @file llblockdata.cpp - * @brief Image block structure - * - * $LicenseInfo:firstyear=2010&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 "linden_common.h" - -#include "llblockdata.h" -#include "llmath.h" - -LLBlockData::LLBlockData(const U32 type) -{ - mType = type; - mWidth = 0; - mHeight = 0; - mRowStride = 0; - mData = NULL; -} - -void LLBlockData::setData(U8 *data, const U32 width, const U32 height, const U32 row_stride) -{ - mData = data; - mWidth = width; - mHeight = height; - if (row_stride) - { - mRowStride = row_stride; - } - else - { - mRowStride = width * 4; - } -} - -U32 LLBlockData::getType() const -{ - return mType; -} - - -U8 *LLBlockData::getData() const -{ - return mData; -} - -U32 LLBlockData::getSize() const -{ - return mWidth*mHeight; -} - -U32 LLBlockData::getWidth() const -{ - return mWidth; -} -U32 LLBlockData::getHeight() const -{ - return mHeight; -} - -U32 LLBlockData::getRowStride() const -{ - return mRowStride; -} - -LLBlockDataU32::LLBlockDataU32() : LLBlockData(BLOCK_TYPE_U32) -{ - mPrecision = 32; -} - -void LLBlockDataU32::setData(U32 *data, const U32 width, const U32 height, const U32 row_stride) -{ - LLBlockData::setData((U8 *)data, width, height, row_stride); -} - -U32 LLBlockDataU32::getSize() const -{ - return mWidth*mHeight*4; -} - -void LLBlockDataU32::setPrecision(const U32 bits) -{ - mPrecision = bits; -} - -U32 LLBlockDataU32::getPrecision() const -{ - return mPrecision; -} - -void LLBlockDataF32::setPrecision(const U32 bits) -{ - mPrecision = bits; -} - -U32 LLBlockDataF32::getPrecision() const -{ - return mPrecision; -} - -void LLBlockDataF32::setData(F32 *data, const U32 width, const U32 height, const U32 row_stride) -{ - LLBlockData::setData((U8 *)data, width, height, row_stride); -} - -void LLBlockDataF32::setMin(const F32 min) -{ - mMin = min; -} - -void LLBlockDataF32::setMax(const F32 max) -{ - mMax = max; -} - -void LLBlockDataF32::calcMinMax() -{ - U32 x, y; - - mMin = *(F32*)mData; - mMax = mMin; - - for (y = 0; y < mHeight; y++) - { - for (x = 0; x < mWidth; x++) - { - F32 data = *(F32*)(mData + y*mRowStride + x*4); - mMin = llmin(data, mMin); - mMax = llmax(data, mMax); - } - } -} - -F32 LLBlockDataF32::getMin() const -{ - return mMin; -} - -F32 LLBlockDataF32::getMax() const -{ - return mMax; -} diff --git a/indra/llkdu/llblockdata.h b/indra/llkdu/llblockdata.h deleted file mode 100644 index dcc847e7e2..0000000000 --- a/indra/llkdu/llblockdata.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @file llblockdata.h - * @brief Image block structure - * - * $LicenseInfo:firstyear=2010&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_LLBLOCKDATA_H -#define LL_LLBLOCKDATA_H - -#include "stdtypes.h" - -////////////////////////////////////////////////// -// -// This class stores all of the information about -// a single channel of raw data, either integer -// or floating point. -// -class LLBlockData -{ -protected: - U32 mType; - U32 mWidth; - U32 mHeight; - U32 mRowStride; - U8 *mData; -public: - enum - { - BLOCK_TYPE_U32 = 1, - BLOCK_TYPE_F32 = 2 - }; - - LLBlockData(const U32 type); - virtual ~LLBlockData() {} - - void setData(U8 *data, const U32 width, const U32 height, const U32 row_stride = 0); - - U32 getType() const; - U8 *getData() const; - virtual U32 getSize() const; - U32 getWidth() const; - U32 getHeight() const; - U32 getRowStride() const; -}; - -class LLBlockDataU32 : public LLBlockData -{ -protected: - U32 mPrecision; -public: - LLBlockDataU32(); - - void setData(U32 *data, const U32 width, const U32 height, const U32 row_stride = 0); - void setPrecision(const U32 bits); - - /*virtual*/ U32 getSize() const; - U32 getPrecision() const; -}; - -class LLBlockDataF32 : public LLBlockData -{ -protected: - U32 mPrecision; - F32 mMin; - F32 mMax; -public: - LLBlockDataF32() - : LLBlockData(LLBlockData::BLOCK_TYPE_F32), - mPrecision(0), - mMin(0.f), - mMax(0.f) - {}; - - void setData(F32 *data, const U32 width, const U32 height, const U32 row_stride = 0); - - void setPrecision(const U32 bits); - void setMin(const F32 min); - void setMax(const F32 max); - - void calcMinMax(); - - U32 getPrecision() const; - F32 getMin() const; - F32 getMax() const; -}; - -#endif // LL_LLBLOCKDATA_H diff --git a/indra/llkdu/llblockdecoder.cpp b/indra/llkdu/llblockdecoder.cpp deleted file mode 100644 index 3daa016591..0000000000 --- a/indra/llkdu/llblockdecoder.cpp +++ /dev/null @@ -1,270 +0,0 @@ - /** - * @file llblockdecoder.cpp - * @brief Image block decompression - * - * $LicenseInfo:firstyear=2010&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 "linden_common.h" - -#include "llblockdecoder.h" - -// KDU core header files -#include "kdu_elementary.h" -#include "kdu_messaging.h" -#include "kdu_params.h" -#include "kdu_compressed.h" -#include "kdu_sample_processing.h" - -#include "llkdumem.h" - -#include "llblockdata.h" -#include "llerror.h" - - -BOOL LLBlockDecoder::decodeU32(LLBlockDataU32 &block_data, U8 *source_data, const U32 source_size) const -{ - U32 width, height; - - llassert(source_data); - - LLKDUMemSource source(source_data, source_size); - - source.reset(); - - kdu_codestream codestream; - - codestream.create(&source); - codestream.set_fast(); - - kdu_dims dims; - codestream.get_dims(0,dims); - llassert(codestream.get_num_components() == 1); - - width = dims.size.x; - height = dims.size.y; - - // Assumes U32 data. - U8 *output = block_data.getData(); - - kdu_dims tile_indices; - codestream.get_valid_tiles(tile_indices); - - kdu_coords tpos; - tpos.x = 0; - tpos.y = 0; - - // Now we are ready to walk through the tiles processing them one-by-one. - while (tpos.y < tile_indices.size.y) - { - while (tpos.x < tile_indices.size.x) - { - kdu_tile tile = codestream.open_tile(tpos+tile_indices.pos); - - kdu_resolution res = tile.access_component(0).access_resolution(); - kdu_dims tile_dims; - res.get_dims(tile_dims); - kdu_coords offset = tile_dims.pos - dims.pos; - int row_gap = block_data.getRowStride(); // inter-row separation - kdu_byte *buf = output + offset.y*row_gap + offset.x*4; - - kdu_tile_comp tile_comp = tile.access_component(0); - bool reversible = tile_comp.get_reversible(); - U32 precision = tile_comp.get_bit_depth(); - U32 precision_scale = 1 << precision; - llassert(precision >= 8); // Else would have used 16 bit representation - - kdu_resolution comp_res = tile_comp.access_resolution(); // Get top resolution - kdu_dims comp_dims; - comp_res.get_dims(comp_dims); - - bool use_shorts = (tile_comp.get_bit_depth(true) <= 16); - - kdu_line_buf line; - kdu_sample_allocator allocator; - kdu_pull_ifc engine; - - line.pre_create(&allocator, comp_dims.size.x, reversible, use_shorts); - if (res.which() == 0) // No DWT levels used - { - engine = kdu_decoder(res.access_subband(LL_BAND), &allocator, use_shorts); - } - else - { - engine = kdu_synthesis(res, &allocator, use_shorts); - } - allocator.finalize(); // Actually creates buffering resources - - line.create(); // Grabs resources from the allocator. - - // Do the actual processing - while (tile_dims.size.y--) - { - engine.pull(line, true); - int width = line.get_width(); - - llassert(line.get_buf32()); - llassert(!line.is_absolute()); - // Decompressed samples have a 32-bit representation (integer or float) - kdu_sample32 *sp = line.get_buf32(); - // Transferring normalized floating point data. - U32 *dest_u32 = (U32 *)buf; - for (; width > 0; width--, sp++, dest_u32++) - { - if (sp->fval < -0.5f) - { - *dest_u32 = 0; - } - else - { - *dest_u32 = (U32)((sp->fval + 0.5f)*precision_scale); - } - } - buf += row_gap; - } - engine.destroy(); - tile.close(); - tpos.x++; - } - tpos.y++; - tpos.x = 0; - } - codestream.destroy(); - - return TRUE; -} - -BOOL LLBlockDecoder::decodeF32(LLBlockDataF32 &block_data, U8 *source_data, const U32 source_size, const F32 min, const F32 max) const -{ - U32 width, height; - F32 range, range_inv, float_offset; - bool use_shorts = false; - - range = max - min; - range_inv = 1.f / range; - float_offset = 0.5f*(max + min); - - llassert(source_data); - - LLKDUMemSource source(source_data, source_size); - - source.reset(); - - kdu_codestream codestream; - - codestream.create(&source); - codestream.set_fast(); - - kdu_dims dims; - codestream.get_dims(0,dims); - llassert(codestream.get_num_components() == 1); - - width = dims.size.x; - height = dims.size.y; - - // Assumes F32 data. - U8 *output = block_data.getData(); - - kdu_dims tile_indices; - codestream.get_valid_tiles(tile_indices); - - kdu_coords tpos; - tpos.x = 0; - tpos.y = 0; - - // Now we are ready to walk through the tiles processing them one-by-one. - while (tpos.y < tile_indices.size.y) - { - while (tpos.x < tile_indices.size.x) - { - kdu_tile tile = codestream.open_tile(tpos+tile_indices.pos); - - kdu_resolution res = tile.access_component(0).access_resolution(); - kdu_dims tile_dims; - res.get_dims(tile_dims); - kdu_coords offset = tile_dims.pos - dims.pos; - int row_gap = block_data.getRowStride(); // inter-row separation - kdu_byte *buf = output + offset.y*row_gap + offset.x*4; - - kdu_tile_comp tile_comp = tile.access_component(0); - bool reversible = tile_comp.get_reversible(); - - kdu_resolution comp_res = tile_comp.access_resolution(); // Get top resolution - kdu_dims comp_dims; - comp_res.get_dims(comp_dims); - - kdu_line_buf line; - kdu_sample_allocator allocator; - kdu_pull_ifc engine; - - line.pre_create(&allocator, comp_dims.size.x, reversible, use_shorts); - if (res.which() == 0) // No DWT levels used - { - engine = kdu_decoder(res.access_subband(LL_BAND), &allocator, use_shorts); - } - else - { - engine = kdu_synthesis(res, &allocator, use_shorts); - } - allocator.finalize(); // Actually creates buffering resources - - line.create(); // Grabs resources from the allocator. - - // Do the actual processing - while (tile_dims.size.y--) - { - engine.pull(line, true); - int width = line.get_width(); - - llassert(line.get_buf32()); - llassert(!line.is_absolute()); - // Decompressed samples have a 32-bit representation (integer or float) - kdu_sample32 *sp = line.get_buf32(); - // Transferring normalized floating point data. - F32 *dest_f32 = (F32 *)buf; - for (; width > 0; width--, sp++, dest_f32++) - { - if (sp->fval < -0.5f) - { - *dest_f32 = min; - } - else if (sp->fval > 0.5f) - { - *dest_f32 = max; - } - else - { - *dest_f32 = (sp->fval) * range + float_offset; - } - } - buf += row_gap; - } - engine.destroy(); - tile.close(); - tpos.x++; - } - tpos.y++; - tpos.x = 0; - } - codestream.destroy(); - return TRUE; -} diff --git a/indra/llkdu/llblockdecoder.h b/indra/llkdu/llblockdecoder.h deleted file mode 100644 index 97959d338e..0000000000 --- a/indra/llkdu/llblockdecoder.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file llblockdecoder.h - * @brief Image block decompression - * - * $LicenseInfo:firstyear=2010&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_LLBLOCKDECODER_H -#define LL_LLBLOCKDECODER_H - -#include "stdtypes.h" - -class LLBlockDataU32; -class LLBlockDataF32; - -class LLBlockDecoder -{ -public: - BOOL decodeU32(LLBlockDataU32 &block_data, U8 *source_data, const U32 source_size) const; - BOOL decodeF32(LLBlockDataF32 &block_data, U8 *source_data, const U32 source_size, const F32 min, const F32 max) const; -}; - -#endif // LL_LLBLOCKDECODER_H diff --git a/indra/llkdu/llblockencoder.cpp b/indra/llkdu/llblockencoder.cpp deleted file mode 100644 index 759eaf65f9..0000000000 --- a/indra/llkdu/llblockencoder.cpp +++ /dev/null @@ -1,340 +0,0 @@ - /** - * @file llblockencoder.cpp - * @brief Image block compression - * - * $LicenseInfo:firstyear=2010&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 "linden_common.h" - -#include "llblockencoder.h" - -// KDU core header files -#include "kdu_elementary.h" -#include "kdu_messaging.h" -#include "kdu_params.h" -#include "kdu_compressed.h" -#include "kdu_sample_processing.h" - -#include "llkdumem.h" - -#include "llblockdata.h" -#include "llerror.h" - -LLBlockEncoder::LLBlockEncoder() -{ - mBPP = 0.f; -} - -U8 *LLBlockEncoder::encode(const LLBlockData &block_data, U32 &output_size) const -{ - switch (block_data.getType()) - { - case LLBlockData::BLOCK_TYPE_U32: - { - LLBlockDataU32 &bd_u32 = (LLBlockDataU32 &)block_data; - return encodeU32(bd_u32, output_size); - } - case LLBlockData::BLOCK_TYPE_F32: - { - LLBlockDataF32 &bd_f32 = (LLBlockDataF32 &)block_data; - return encodeF32(bd_f32, output_size); - } - default: - llerrs << "Unsupported block type!" << llendl; - output_size = 0; - return NULL; - } -} - -U8 *LLBlockEncoder::encodeU32(const LLBlockDataU32 &block_data, U32 &output_size) const -{ - // OK, for now, just use the standard KDU encoder, with a single channel - // integer channel. - - // Collect simple arguments. - bool allow_rate_prediction, allow_shorts, mem, quiet, no_weights; - - allow_rate_prediction = true; - allow_shorts = false; - no_weights = false; - bool use_absolute = false; - mem = false; - quiet = false; - - // Set codestream options - siz_params siz; - S16 precision = block_data.getPrecision(); - - siz.set(Sdims,0,0,(U16)block_data.getHeight()); - siz.set(Sdims,0,1,(U16)block_data.getWidth()); - siz.set(Ssigned,0,0,false); - siz.set(Scomponents,0,0,1); - siz.set(Sprecision,0,0, precision); - - // Construct the `kdu_codestream' object and parse all remaining arguments. - output_size = block_data.getSize(); - if (output_size < 1000) - { - output_size = 1000; - } - - U8 *output_buffer = new U8[output_size]; - - LLKDUMemTarget output(output_buffer, output_size, block_data.getSize()); - - kdu_codestream codestream; - codestream.create(&siz,&output); - - codestream.access_siz()->parse_string("Clayers=1"); - codestream.access_siz()->finalize_all(); - - kdu_tile tile = codestream.open_tile(kdu_coords(0,0)); - - // Open tile-components and create processing engines and resources - kdu_dims dims; - kdu_sample_allocator allocator; - kdu_tile_comp tile_comp; - kdu_line_buf line; - kdu_push_ifc engine; - - tile_comp = tile.access_component(0); - kdu_resolution res = tile_comp.access_resolution(); // Get top resolution - - res.get_dims(dims); - - line.pre_create(&allocator,dims.size.x, use_absolute, allow_shorts); - - if (res.which() == 0) // No DWT levels (should not occur in this example) - { - engine = kdu_encoder(res.access_subband(LL_BAND),&allocator, use_absolute); - } - else - { - engine = kdu_analysis(res,&allocator, use_absolute); - } - - allocator.finalize(); // Actually creates buffering resources - line.create(); // Grabs resources from the allocator. - - // Now walk through the lines of the buffer, pushing them into the - // relevant tile-component processing engines. - - U32 *source_u32 = NULL; - F32 scale_inv = 1.f / (1 << precision); - - S32 y; - for (y = 0; y < dims.size.y; y++) - { - source_u32 = (U32*)(block_data.getData() + y * block_data.getRowStride()); - kdu_sample32 *dest = line.get_buf32(); - for (S32 n=dims.size.x; n > 0; n--, dest++, source_u32++) - { - // Just pack it in, for now. - dest->fval = (F32)(*source_u32) * scale_inv - 0.5f;// - 0.5f; - } - engine.push(line, true); - } - - // Cleanup - engine.destroy(); // engines are interfaces; no default destructors - - // Produce the final compressed output. - kdu_long layer_bytes[1] = {0}; - - layer_bytes[0] = (kdu_long) (mBPP*block_data.getWidth()*block_data.getHeight()); - // Here we are not requesting specific sizes for any of the 12 - // quality layers. As explained in the description of - // "kdu_codestream::flush" (see "kdu_compressed.h"), the rate allocator - // will then assign the layers in such a way as to achieve roughly - // two quality layers per octave change in bit-rate, with the final - // layer reaching true lossless quality. - - codestream.flush(layer_bytes,1); - // You can see how many bytes were assigned - // to each quality layer by looking at the entries of `layer_bytes' here. - // The flush function can do a lot of interesting things which you may - // want to spend some time looking into. In addition to targeting - // specific bit-rates for each quality layer, it can be configured to - // use rate-distortion slope thresholds of your choosing and to return - // the thresholds which it finds to be best for any particular set of - // target layer sizes. This opens the door to feedback-oriented rate - // control for video. You should also look into the - // "kdu_codestream::set_max_bytes" and - // "kdu_codestream::set_min_slope_threshold" functions which can be - // used to significantly speed up compression. - codestream.destroy(); // All done: simple as that. - - // Now that we're done encoding, create the new data buffer for the compressed - // image and stick it there. - - U8 *output_data = new U8[output_size]; - - memcpy(output_data, output_buffer, output_size); - - output.close(); // Not really necessary here. - - return output_data; -} - -U8 *LLBlockEncoder::encodeF32(const LLBlockDataF32 &block_data, U32 &output_size) const -{ - // OK, for now, just use the standard KDU encoder, with a single channel - // integer channel. - - // Collect simple arguments. - bool allow_rate_prediction, allow_shorts, mem, quiet, no_weights; - - allow_rate_prediction = true; - allow_shorts = false; - no_weights = false; - bool use_absolute = false; - mem = false; - quiet = false; - - F32 min, max, range, range_inv, offset; - min = block_data.getMin(); - max = block_data.getMax(); - range = max - min; - range_inv = 1.f / range; - offset = 0.5f*(max + min); - - // Set codestream options - siz_params siz; - S16 precision = block_data.getPrecision(); // Assume precision is always 32 bits for floating point. - - siz.set(Sdims,0,0,(U16)block_data.getHeight()); - siz.set(Sdims,0,1,(U16)block_data.getWidth()); - siz.set(Ssigned,0,0,false); - siz.set(Scomponents,0,0,1); - siz.set(Sprecision,0,0, precision); - - // Construct the `kdu_codestream' object and parse all remaining arguments. - output_size = block_data.getSize(); - if (output_size < 1000) - { - output_size = 1000; - } - - U8 *output_buffer = new U8[output_size*2]; - - LLKDUMemTarget output(output_buffer, output_size, block_data.getSize()); - - kdu_codestream codestream; - codestream.create(&siz,&output); - - codestream.access_siz()->parse_string("Clayers=1"); - codestream.access_siz()->finalize_all(); - - kdu_tile tile = codestream.open_tile(kdu_coords(0,0)); - - // Open tile-components and create processing engines and resources - kdu_dims dims; - kdu_sample_allocator allocator; - kdu_tile_comp tile_comp; - kdu_line_buf line; - kdu_push_ifc engine; - - tile_comp = tile.access_component(0); - kdu_resolution res = tile_comp.access_resolution(); // Get top resolution - - res.get_dims(dims); - - line.pre_create(&allocator,dims.size.x, use_absolute, allow_shorts); - - if (res.which() == 0) // No DWT levels (should not occur in this example) - { - engine = kdu_encoder(res.access_subband(LL_BAND),&allocator, use_absolute); - } - else - { - engine = kdu_analysis(res,&allocator, use_absolute); - } - - allocator.finalize(); // Actually creates buffering resources - line.create(); // Grabs resources from the allocator. - - // Now walk through the lines of the buffer, pushing them into the - // relevant tile-component processing engines. - - F32 *source_f32 = NULL; - - S32 y; - for (y = 0; y < dims.size.y; y++) - { - source_f32 = (F32*)(block_data.getData() + y * block_data.getRowStride()); - kdu_sample32 *dest = line.get_buf32(); - for (S32 n=dims.size.x; n > 0; n--, dest++, source_f32++) - { - dest->fval = ((*source_f32) - offset) * range_inv; - } - engine.push(line, true); - } - - // Cleanup - engine.destroy(); // engines are interfaces; no default destructors - - // Produce the final compressed output. - kdu_long layer_bytes[1] = {0}; - - layer_bytes[0] = (kdu_long) (mBPP*block_data.getWidth()*block_data.getHeight()); - // Here we are not requesting specific sizes for any of the 12 - // quality layers. As explained in the description of - // "kdu_codestream::flush" (see "kdu_compressed.h"), the rate allocator - // will then assign the layers in such a way as to achieve roughly - // two quality layers per octave change in bit-rate, with the final - // layer reaching true lossless quality. - - codestream.flush(layer_bytes,1); - // You can see how many bytes were assigned - // to each quality layer by looking at the entries of `layer_bytes' here. - // The flush function can do a lot of interesting things which you may - // want to spend some time looking into. In addition to targeting - // specific bit-rates for each quality layer, it can be configured to - // use rate-distortion slope thresholds of your choosing and to return - // the thresholds which it finds to be best for any particular set of - // target layer sizes. This opens the door to feedback-oriented rate - // control for video. You should also look into the - // "kdu_codestream::set_max_bytes" and - // "kdu_codestream::set_min_slope_threshold" functions which can be - // used to significantly speed up compression. - codestream.destroy(); // All done: simple as that. - - // Now that we're done encoding, create the new data buffer for the compressed - // image and stick it there. - - U8 *output_data = new U8[output_size]; - - memcpy(output_data, output_buffer, output_size); - - output.close(); // Not really necessary here. - - delete[] output_buffer; - - return output_data; -} - - -void LLBlockEncoder::setBPP(const F32 bpp) -{ - mBPP = bpp; -} diff --git a/indra/llkdu/llblockencoder.h b/indra/llkdu/llblockencoder.h deleted file mode 100644 index 21381a27fa..0000000000 --- a/indra/llkdu/llblockencoder.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @file llblockencoder.h - * @brief Image block compression - * - * $LicenseInfo:firstyear=2010&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_LLBLOCKENCODER_H -#define LL_LLBLOCKENCODER_H - -#include "stdtypes.h" - -class LLBlockData; -class LLBlockDataU32; -class LLBlockDataF32; - -class LLBlockEncoder -{ - F32 mBPP; // bits per point -public: - LLBlockEncoder(); - U8 *encode(const LLBlockData &block_data, U32 &output_size) const; - U8 *encodeU32(const LLBlockDataU32 &block_data, U32 &output_size) const; - U8 *encodeF32(const LLBlockDataF32 &block_data, U32 &output_size) const; - - void setBPP(const F32 bpp); -}; - -#endif // LL_LLBLOCKENCODER_H - -- cgit v1.2.3 From a991bd7f90157a9cc661ef17a6f96e8473e3bd58 Mon Sep 17 00:00:00 2001 From: callum Date: Thu, 2 Dec 2010 14:50:57 -0800 Subject: SOCIAL-311 FIX Media browser has too many oddities to be useful for viewer web apps Completes MVP --- indra/llplugin/llpluginclassmedia.cpp | 4 +- indra/llplugin/llpluginclassmedia.h | 4 +- indra/newview/llfloaterwebcontent.cpp | 59 ++++++++++++++++------- indra/newview/llfloaterwebcontent.h | 5 +- indra/newview/skins/default/textures/textures.xml | 4 +- 5 files changed, 52 insertions(+), 24 deletions(-) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index de4456aa4e..e6c901dd5c 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -1049,8 +1049,8 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) } else if(message_name == "link_hovered") { - // Link and text are not currently used -- the tooltip hover text is taken from the "title". - // message.getValue("link"); + // text is not currently used -- the tooltip hover text is taken from the "title". + mHoverLink = message.getValue("link"); mHoverText = message.getValue("title"); // message.getValue("text"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index fa4dc2b43f..abc472f501 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -242,8 +242,9 @@ public: std::string getAuthURL() const { return mAuthURL; }; std::string getAuthRealm() const { return mAuthRealm; }; - // This is valid during MEDIA_EVENT_LINK_HOVERED + // These are valid during MEDIA_EVENT_LINK_HOVERED std::string getHoverText() const { return mHoverText; }; + std::string getHoverLink() const { return mHoverLink; }; std::string getMediaName() const { return mMediaName; }; std::string getMediaDescription() const { return mMediaDescription; }; @@ -385,6 +386,7 @@ protected: std::string mAuthURL; std::string mAuthRealm; std::string mHoverText; + std::string mHoverLink; ///////////////////////////////////////// // media_time class diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 8e5638f549..31b6c3fc49 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -37,26 +37,26 @@ #include "llfloaterwebcontent.h" -LLFloaterWebContent::LLFloaterWebContent(const LLSD& key) - : LLFloater(key) +LLFloaterWebContent::LLFloaterWebContent( const LLSD& key ) + : LLFloater( key ) { - mCommitCallbackRegistrar.add("WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this)); - mCommitCallbackRegistrar.add("WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this)); - mCommitCallbackRegistrar.add("WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this)); + mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this )); + mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this )); + mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this )); - mCommitCallbackRegistrar.add("WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this)); + mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this )); } BOOL LLFloaterWebContent::postBuild() { // these are used in a bunch of places so cache them - mWebBrowser = getChild("webbrowser"); - mAddressCombo = getChild("address"); - mStatusBarText = getChild("statusbartext"); - mStatusBarProgress = getChild("statusbarprogress"); + mWebBrowser = getChild< LLMediaCtrl >( "webbrowser" ); + mAddressCombo = getChild< LLComboBox >( "address" ); + mStatusBarText = getChild< LLTextBox >( "statusbartext" ); + mStatusBarProgress = getChild("statusbarprogress" ); // observe browser events - mWebBrowser->addObserver(this); + mWebBrowser->addObserver( this ); // these button are always enabled getChildView("reload")->setEnabled( true ); @@ -65,7 +65,7 @@ BOOL LLFloaterWebContent::postBuild() } //static -void LLFloaterWebContent::create(const std::string &url, const std::string& target, const std::string& uuid) +void LLFloaterWebContent::create( const std::string &url, const std::string& target, const std::string& uuid ) { lldebugs << "url = " << url << ", target = " << target << ", uuid = " << uuid << llendl; @@ -194,11 +194,22 @@ void LLFloaterWebContent::onClose(bool app_quitting) destroy(); } +// virtual +void LLFloaterWebContent::draw() +{ + // this is asychronous so we need to keep checking + getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() ); + getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() ); + + LLFloater::draw(); +} + +// virtual void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) { if(event == MEDIA_EVENT_LOCATION_CHANGED) { - const std::string url = self->getStatusText(); + const std::string url = self->getLocation(); if ( url.length() ) mStatusBarText->setText( url ); @@ -211,11 +222,11 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); - // manually decide on the state of this button + // toggle visibility of these buttons based on browser state getChildView("reload")->setVisible( false ); getChildView("stop")->setVisible( true ); - // turn "on" progress bar now we're loaded + // turn "on" progress bar now we're about to start loading mStatusBarProgress->setVisible( true ); } else if(event == MEDIA_EVENT_NAVIGATE_COMPLETE) @@ -224,12 +235,16 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent getChildView("back")->setEnabled( self->getHistoryBackAvailable() ); getChildView("forward")->setEnabled( self->getHistoryForwardAvailable() ); - // manually decide on the state of this button + // toggle visibility of these buttons based on browser state getChildView("reload")->setVisible( true ); getChildView("stop")->setVisible( false ); // turn "off" progress bar now we're loaded mStatusBarProgress->setVisible( false ); + + // we populate the status bar with URLs as they change so clear it now we're done + const std::string end_str = ""; + mStatusBarText->setText( end_str ); } else if(event == MEDIA_EVENT_CLOSE_REQUEST) { @@ -256,6 +271,11 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent std::string page_title = self->getMediaName(); setTitle( page_title ); } + else if(event == MEDIA_EVENT_LINK_HOVERED ) + { + const std::string link = self->getHoverLink(); + mStatusBarText->setText( link ); + } } void LLFloaterWebContent::set_current_url(const std::string& url) @@ -300,5 +320,10 @@ void LLFloaterWebContent::onClickStop() void LLFloaterWebContent::onEnterAddress() { - mWebBrowser->navigateTo( mAddressCombo->getValue().asString() ); + // make sure there is at least something there. + // (perhaps this test should be for minimum length of a URL) + if ( mAddressCombo->getValue().asString().length() > 0 ) + { + mWebBrowser->navigateTo( mAddressCombo->getValue().asString() ); + }; } diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index b41da57a6f..1effa2c4ab 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -49,8 +49,9 @@ public: static void geometryChanged(const std::string &uuid, S32 x, S32 y, S32 width, S32 height); void geometryChanged(S32 x, S32 y, S32 width, S32 height); - /*virtual*/ BOOL postBuild(); - /*virtual*/ void onClose(bool app_quitting); + /* virtual */ BOOL postBuild(); + /* virtual */ void onClose(bool app_quitting); + /* virtual */ void draw(); // inherited from LLViewerMediaObserver /*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event); diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index b2658d2525..0314ef2cff 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -392,7 +392,7 @@ with the same filename but different name - + @@ -468,7 +468,7 @@ with the same filename but different name - + -- cgit v1.2.3 From 1405d198d60081531edeeb996c2fc07841808335 Mon Sep 17 00:00:00 2001 From: callum Date: Thu, 2 Dec 2010 14:51:25 -0800 Subject: SOCIAL-315 FIX Update Qt/LLQtWebKit version number in the viewer to 4.7.1 from 4.6 --- indra/newview/llfloaterabout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 135137069c..36e26d3fea 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -272,7 +272,7 @@ LLSD LLFloaterAbout::getInfo() } // TODO: Implement media plugin version query - info["QT_WEBKIT_VERSION"] = "4.6 (version number hard-coded)"; + info["QT_WEBKIT_VERSION"] = "4.7.1 (version number hard-coded)"; if (gPacketsIn > 0) { -- cgit v1.2.3 From 922b1f26b7279b5f54562c413c333463fe34473b Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Thu, 2 Dec 2010 18:42:47 -0500 Subject: ESC-211 Metrics data sink - fix delivery by viewer The TextureFetch thread was still stalling out due to a different path that determines whether there is work or not in the thread (uses getPending()) and that had to be harmonized with the changes to runCondition(). I'm not happy with this solution but a refactor of the LLThread tree isn't in the cards right now. --- indra/llcommon/llqueuedthread.h | 2 +- indra/newview/lltexturefetch.cpp | 89 +++++++++++++++++++++++++++++++++++----- indra/newview/lltexturefetch.h | 1 + 3 files changed, 80 insertions(+), 12 deletions(-) diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index c75e0e2bbf..a53b22f6fc 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -179,7 +179,7 @@ public: void waitOnPending(); void printQueueStats(); - S32 getPending(); + virtual S32 getPending(); bool getThreaded() { return mThreaded ? true : false; } // Request accessors diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 3793085e55..dd84290e90 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -568,6 +568,14 @@ public: LLSD * mReportMain; }; +/* + * Count of POST requests outstanding. We maintain the count + * indirectly in the CURL request responder's ctor and dtor and + * use it when determining whether or not to sleep the flag. Can't + * use the LLCurl module's request counter as it isn't thread compatible. + */ +LLAtomic32 curl_post_request_count = 0; + } // end of anonymous namespace @@ -2084,6 +2092,33 @@ bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) return res; } +// Replicates and expands upon the base class's +// getPending() implementation. getPending() and +// runCondition() replicate one another's logic to +// an extent and are sometimes used for the same +// function (deciding whether or not to sleep/pause +// a thread). So the implementations need to stay +// in step, at least until this can be refactored and +// the redundancy eliminated. +// +// May be called from any thread + +//virtual +S32 LLTextureFetch::getPending() +{ + S32 res; + lockData(); + { + LLMutexLock lock(&mQueueMutex); + + res = mRequestQueue.size(); + res += curl_post_request_count; + res += mCommands.size(); + } + unlockData(); + return res; +} + // virtual bool LLTextureFetch::runCondition() { @@ -2100,7 +2135,12 @@ bool LLTextureFetch::runCondition() have_no_commands = mCommands.empty(); } - return ! (have_no_commands && mRequestQueue.empty() && mIdleThread); + + bool have_no_curl_requests(0 == curl_post_request_count); + + return ! (have_no_commands + && have_no_curl_requests + && (mRequestQueue.empty() && mIdleThread)); } ////////////////////////////////////////////////////////////////////////////// @@ -2116,7 +2156,7 @@ void LLTextureFetch::commonUpdate() if (processed > 0) { lldebugs << "processed: " << processed << " messages." << llendl; - } + } } @@ -2766,31 +2806,56 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) * the referenced data is part of a pseudo-closure for * this responder rather than being required for correct * operation. + * + * We don't try very hard with the POST request. We give + * it one shot and that's more-or-less it. With a proper + * refactoring of the LLQueuedThread usage, these POSTs + * could be put in a request object and made more reliable. */ class lcl_responder : public LLCurl::Responder { public: - lcl_responder(volatile bool & reporting_break, + lcl_responder(S32 expected_sequence, + volatile const S32 & live_sequence, + volatile bool & reporting_break, volatile bool & reporting_started) - : LLHTTPClient::Responder(), + : LLCurl::Responder(), + mExpectedSequence(expected_sequence), + mLiveSequence(live_sequence), mReportingBreak(reporting_break), mReportingStarted(reporting_started) - {} + { + curl_post_request_count++; + } + + ~lcl_responder() + { + curl_post_request_count--; + } // virtual void error(U32 status_num, const std::string & reason) { - mReportingBreak = true; + if (mLiveSequence == mExpectedSequence) + { + mReportingBreak = true; + } } // virtual void result(const LLSD & content) { - mReportingBreak = false; - mReportingStarted = true; + if (mLiveSequence == mExpectedSequence) + { + mReportingBreak = false; + mReportingStarted = true; + } } + private: + S32 mExpectedSequence; + volatile const S32 & mLiveSequence; volatile bool & mReportingBreak; volatile bool & mReportingStarted; }; @@ -2799,8 +2864,8 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) return true; static volatile bool reporting_started(false); - static S32 report_sequence(0); - + static volatile S32 report_sequence(0); + // We've already taken over ownership of the LLSD at this point // and can do normal LLSD sharing operations at this point. But // still being careful, regardless. @@ -2826,7 +2891,9 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) fetcher->getCurlRequest().post(mCapsURL, headers, thread1_stats, - new lcl_responder(LLTextureFetch::svMetricsDataBreak, + new lcl_responder(report_sequence, + report_sequence, + LLTextureFetch::svMetricsDataBreak, reporting_started)); } else diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 03e2462058..af30d1bb3b 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -78,6 +78,7 @@ public: S32 getNumHTTPRequests() ; // Public for access by callbacks + S32 getPending(); void lockQueue() { mQueueMutex.lock(); } void unlockQueue() { mQueueMutex.unlock(); } LLTextureFetchWorker* getWorker(const LLUUID& id); -- cgit v1.2.3 From 84a50386be1ef34100e153666389ffacf03e8e8b Mon Sep 17 00:00:00 2001 From: callum Date: Thu, 2 Dec 2010 18:46:26 -0800 Subject: SOCIAL-317 FIX LLWebContentFloater opens popups in the media browser --- indra/newview/llmediactrl.cpp | 13 ++++++++++++- indra/newview/llweb.cpp | 17 +++++++++++++++++ indra/newview/llweb.h | 1 + 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 08d07f9540..eaa2a60938 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -55,6 +55,8 @@ #include "llcheckboxctrl.h" #include "llnotifications.h" #include "lllineeditor.h" +#include "llfloatermediabrowser.h" +#include "llfloaterwebcontent.h" extern BOOL gRestoreGL; @@ -1331,7 +1333,16 @@ void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) { if (response["open"]) { - LLWeb::loadURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]); + std::string floater_name = gFloaterView->getParentFloater(this)->getInstanceName(); + if ( floater_name == "media_browser" ) + { + LLWeb::loadURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]); + } + else + if ( floater_name == "web_content" ) + { + LLWeb::loadWebURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]); + } } else { diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 91a713be56..2ecab2cbdf 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -96,6 +96,23 @@ void LLWeb::loadURL(const std::string& url, const std::string& target, const std } } +// static +void LLWeb::loadWebURL(const std::string& url, const std::string& target, const std::string& uuid) +{ + if(target == "_internal") + { + // Force load in the internal browser, as if with a blank target. + loadWebURLInternal(url, "", uuid); + } + else if (gSavedSettings.getBOOL("UseExternalBrowser") || (target == "_external")) + { + loadURLExternal(url); + } + else + { + loadWebURLInternal(url, target, uuid); + } +} // static void LLWeb::loadURLInternal(const std::string &url, const std::string& target, const std::string& uuid) diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h index 3fe5a4dcad..a74d4b6364 100644 --- a/indra/newview/llweb.h +++ b/indra/newview/llweb.h @@ -58,6 +58,7 @@ public: static void loadURLExternal(const std::string& url, bool async, const std::string& uuid = LLStringUtil::null); // Explicitly open a Web URL using the Web content floater vs. the more general media browser + static void LLWeb::loadWebURL(const std::string& url, const std::string& target, const std::string& uuid); static void loadWebURLInternal(const std::string &url, const std::string& target, const std::string& uuid); static void loadWebURLInternal(const std::string &url) { loadWebURLInternal(url, LLStringUtil::null, LLStringUtil::null); } -- cgit v1.2.3 From abc13fb12faab4d6198fb4496da9559a8ca1d854 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 2 Dec 2010 22:26:49 -0800 Subject: STORM-151 : First shot at compression, not optimzed yet --- indra/llkdu/llimagej2ckdu.cpp | 196 +++++++++++++++++++++++++++++++----------- 1 file changed, 146 insertions(+), 50 deletions(-) diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 147b9829c5..21c91be1f7 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -31,6 +31,38 @@ #include "llpointer.h" #include "llkdumem.h" + +class kdc_flow_control { +public: // Member functions + kdc_flow_control(kdu_image_in_base *img_in, kdu_codestream codestream); + ~kdc_flow_control(); + bool advance_components(); + void process_components(); +private: // Data + + struct kdc_component_flow_control { + public: // Data + kdu_image_in_base *reader; + int vert_subsampling; + int ratio_counter; /* Initialized to 0, decremented by `count_delta'; + when < 0, a new line must be processed, after + which it is incremented by `vert_subsampling'. */ + int initial_lines; + int remaining_lines; + kdu_line_buf *line; + }; + + kdu_codestream codestream; + kdu_dims valid_tile_indices; + kdu_coords tile_idx; + kdu_tile tile; + int num_components; + kdc_component_flow_control *components; + int count_delta; // Holds the minimum of the `vert_subsampling' fields. + kdu_multi_analysis engine; + kdu_long max_buffer_memory; +}; + // // Kakadu specific implementation // @@ -38,7 +70,7 @@ void set_default_colour_weights(kdu_params *siz); const char* engineInfoLLImageJ2CKDU() { - return "KDU"; + return "KDU v6.4.1"; } LLImageJ2CKDU* createLLImageJ2CKDU() @@ -474,16 +506,14 @@ BOOL LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, BOOL reversible) { // Collect simple arguments. -/* bool transpose, vflip, hflip; - bool allow_rate_prediction, allow_shorts, mem, quiet, no_weights; + bool allow_rate_prediction, mem, quiet, no_weights; int cpu_iterations; std::ostream *record_stream; transpose = false; record_stream = NULL; allow_rate_prediction = true; - allow_shorts = true; no_weights = false; cpu_iterations = -1; mem = false; @@ -620,51 +650,24 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co codestream.change_appearance(transpose,vflip,hflip); // Now we are ready for sample data processing. - - int x_tnum; - kdu_dims tile_indices; codestream.get_valid_tiles(tile_indices); - kdc_flow_control **tile_flows = new kdc_flow_control *[tile_indices.size.x]; - for (x_tnum=0; x_tnum < tile_indices.size.x; x_tnum++) - { - tile_flows[x_tnum] = new kdc_flow_control(&mem_in,codestream,x_tnum,allow_shorts); - } - bool done = false; - - while (!done) - { - while (!done) - { // Process a row of tiles line by line. - done = true; - for (x_tnum=0; x_tnum < tile_indices.size.x; x_tnum++) - { - if (tile_flows[x_tnum]->advance_components()) - { - done = false; - tile_flows[x_tnum]->process_components(); - } - } - } - for (x_tnum=0; x_tnum < tile_indices.size.x; x_tnum++) - { - if (tile_flows[x_tnum]->advance_tile()) - { - done = false; - } - } - } - int sample_bytes = 0; - for (x_tnum=0; x_tnum < tile_indices.size.x; x_tnum++) - { - sample_bytes += tile_flows[x_tnum]->get_buffer_memory(); - delete tile_flows[x_tnum]; - } - delete [] tile_flows; - - // Produce the compressed output. - - codestream.flush(layer_bytes,num_layer_specs, NULL, true, false); + kdc_flow_control *tile = new kdc_flow_control(&mem_in,codestream); + bool done = false; + while (!done) + { + // Process line by line + done = true; + if (tile->advance_components()) + { + done = false; + tile->process_components(); + } + } + + // Produce the compressed output + codestream.flush(layer_bytes,num_layer_specs); // Cleanup + delete tile; codestream.destroy(); if (record_stream != NULL) @@ -692,9 +695,6 @@ BOOL LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co } return TRUE; - */ - // Compression not implemented yet - return FALSE; } BOOL LLImageJ2CKDU::getMetadata(LLImageJ2C &base) @@ -1014,3 +1014,99 @@ separation between consecutive rows in the real buffer. */ } return TRUE; } + +// kdc_flow_control + +kdc_flow_control::kdc_flow_control (kdu_image_in_base *img_in, kdu_codestream codestream) +{ + int n; + + this->codestream = codestream; + codestream.get_valid_tiles(valid_tile_indices); + tile_idx = valid_tile_indices.pos; + tile = codestream.open_tile(tile_idx,NULL); + + // Set up the individual components + num_components = codestream.get_num_components(true); + components = new kdc_component_flow_control[num_components]; + count_delta = 0; + kdc_component_flow_control *comp = components; + for (n = 0; n < num_components; n++, comp++) + { + comp->line = NULL; + comp->reader = img_in; + kdu_coords subsampling; + codestream.get_subsampling(n,subsampling,true); + kdu_dims dims; + codestream.get_tile_dims(tile_idx,n,dims,true); + comp->vert_subsampling = subsampling.y; + if ((n == 0) || (comp->vert_subsampling < count_delta)) + { + count_delta = comp->vert_subsampling; + } + comp->ratio_counter = 0; + comp->remaining_lines = comp->initial_lines = dims.size.y; + } + assert(num_components > 0); + + tile.set_components_of_interest(num_components); + max_buffer_memory = engine.create(codestream,tile,false,NULL,false,1,NULL,NULL,false); +} + +kdc_flow_control::~kdc_flow_control() +{ + if (components != NULL) + delete[] components; + if (engine.exists()) + engine.destroy(); +} + +bool kdc_flow_control::advance_components() +{ + bool found_line = false; + while (!found_line) + { + bool all_done = true; + kdc_component_flow_control *comp = components; + for (int n = 0; n < num_components; n++, comp++) + { + assert(comp->ratio_counter >= 0); + if (comp->remaining_lines > 0) + { + all_done = false; + comp->ratio_counter -= count_delta; + if (comp->ratio_counter < 0) + { + found_line = true; + comp->line = engine.exchange_line(n,NULL,NULL); + assert(comp->line != NULL); + if (comp->line->get_width()) + { + comp->reader->get(n,*(comp->line),0); + } + } + } + } + if (all_done) + return false; + } + return true; +} + +void kdc_flow_control::process_components() +{ + kdc_component_flow_control *comp = components; + for (int n = 0; n < num_components; n++, comp++) + { + if (comp->ratio_counter < 0) + { + comp->ratio_counter += comp->vert_subsampling; + assert(comp->ratio_counter >= 0); + assert(comp->remaining_lines > 0); + comp->remaining_lines--; + assert(comp->line != NULL); + engine.exchange_line(n,comp->line,NULL); + comp->line = NULL; + } + } +} -- cgit v1.2.3 From 1c946e8e4dcb6a6fcdfafeca82d9ba1db9f09e54 Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 3 Dec 2010 10:34:54 -0800 Subject: SOCIAL-318 FIX Example plugin doesn't render anything --- .../media_plugins/example/media_plugin_example.cpp | 733 +++++++++------------ 1 file changed, 329 insertions(+), 404 deletions(-) diff --git a/indra/media_plugins/example/media_plugin_example.cpp b/indra/media_plugins/example/media_plugin_example.cpp index f8a871930e..da7de01799 100644 --- a/indra/media_plugins/example/media_plugin_example.cpp +++ b/indra/media_plugins/example/media_plugin_example.cpp @@ -6,21 +6,21 @@ * $LicenseInfo:firstyear=2008&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$ * @endcond @@ -39,48 +39,48 @@ //////////////////////////////////////////////////////////////////////////////// // class MediaPluginExample : - public MediaPluginBase + public MediaPluginBase { - public: - MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ); - ~MediaPluginExample(); - - /*virtual*/ void receiveMessage( const char* message_string ); - - private: - bool init(); - void update( F64 milliseconds ); - void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ); - bool mFirstTime; - - time_t mLastUpdateTime; - enum Constants { ENumObjects = 10 }; - unsigned char* mBackgroundPixels; - int mColorR[ ENumObjects ]; - int mColorG[ ENumObjects ]; - int mColorB[ ENumObjects ]; - int mXpos[ ENumObjects ]; - int mYpos[ ENumObjects ]; - int mXInc[ ENumObjects ]; - int mYInc[ ENumObjects ]; - int mBlockSize[ ENumObjects ]; - bool mMouseButtonDown; - bool mStopAction; + public: + MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ); + ~MediaPluginExample(); + + /*virtual*/ void receiveMessage( const char* message_string ); + + private: + bool init(); + void update( F64 milliseconds ); + void write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ); + bool mFirstTime; + + time_t mLastUpdateTime; + enum Constants { ENumObjects = 10 }; + unsigned char* mBackgroundPixels; + int mColorR[ ENumObjects ]; + int mColorG[ ENumObjects ]; + int mColorB[ ENumObjects ]; + int mXpos[ ENumObjects ]; + int mYpos[ ENumObjects ]; + int mXInc[ ENumObjects ]; + int mYInc[ ENumObjects ]; + int mBlockSize[ ENumObjects ]; + bool mMouseButtonDown; + bool mStopAction; }; //////////////////////////////////////////////////////////////////////////////// // MediaPluginExample::MediaPluginExample( LLPluginInstance::sendMessageFunction host_send_func, void *host_user_data ) : - MediaPluginBase( host_send_func, host_user_data ) + MediaPluginBase( host_send_func, host_user_data ) { - mFirstTime = true; - mWidth = 0; - mHeight = 0; - mDepth = 4; - mPixels = 0; - mMouseButtonDown = false; - mStopAction = false; - mLastUpdateTime = 0; + mFirstTime = true; + mWidth = 0; + mHeight = 0; + mDepth = 4; + mPixels = 0; + mMouseButtonDown = false; + mStopAction = false; + mLastUpdateTime = 0; } //////////////////////////////////////////////////////////////////////////////// @@ -93,395 +93,320 @@ MediaPluginExample::~MediaPluginExample() // void MediaPluginExample::receiveMessage( const char* message_string ) { - LLPluginMessage message_in; - - if ( message_in.parse( message_string ) >= 0 ) - { - std::string message_class = message_in.getClass(); - std::string message_name = message_in.getName(); - - if ( message_class == LLPLUGIN_MESSAGE_CLASS_BASE ) - { - if ( message_name == "init" ) - { - LLPluginMessage message( "base", "init_response" ); - LLSD versions = LLSD::emptyMap(); - versions[ LLPLUGIN_MESSAGE_CLASS_BASE ] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; - versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; - versions[ LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; - message.setValueLLSD( "versions", versions ); - - std::string plugin_version = "Example media plugin, Example Version 1.0.0.0"; - message.setValue( "plugin_version", plugin_version ); - sendMessage( message ); - } - else - if ( message_name == "idle" ) - { - // no response is necessary here. - F64 time = message_in.getValueReal( "time" ); - - // Convert time to milliseconds for update() - update( time ); - } - else - if ( message_name == "cleanup" ) - { - // clean up here - } - else - if ( message_name == "shm_added" ) - { - SharedSegmentInfo info; - info.mAddress = message_in.getValuePointer( "address" ); - info.mSize = ( size_t )message_in.getValueS32( "size" ); - std::string name = message_in.getValue( "name" ); - - mSharedSegments.insert( SharedSegmentMap::value_type( name, info ) ); - - } - else - if ( message_name == "shm_remove" ) - { - std::string name = message_in.getValue( "name" ); - - SharedSegmentMap::iterator iter = mSharedSegments.find( name ); - if( iter != mSharedSegments.end() ) - { - if ( mPixels == iter->second.mAddress ) - { - // This is the currently active pixel buffer. - // Make sure we stop drawing to it. - mPixels = NULL; - mTextureSegmentName.clear(); - }; - mSharedSegments.erase( iter ); - } - else - { - //std::cerr << "MediaPluginExample::receiveMessage: unknown shared memory region!" << std::endl; - }; - - // Send the response so it can be cleaned up. - LLPluginMessage message( "base", "shm_remove_response" ); - message.setValue( "name", name ); - sendMessage( message ); - } - else - { - //std::cerr << "MediaPluginExample::receiveMessage: unknown base message: " << message_name << std::endl; - }; - } - else - if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA ) - { - if ( message_name == "init" ) - { - // Plugin gets to decide the texture parameters to use. - LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params" ); - message.setValueS32( "default_width", mWidth ); - message.setValueS32( "default_height", mHeight ); - message.setValueS32( "depth", mDepth ); - message.setValueU32( "internalformat", GL_RGBA ); - message.setValueU32( "format", GL_RGBA ); - message.setValueU32( "type", GL_UNSIGNED_BYTE ); - message.setValueBoolean( "coords_opengl", false ); - sendMessage( message ); - } - else if ( message_name == "size_change" ) - { - std::string name = message_in.getValue( "name" ); - S32 width = message_in.getValueS32( "width" ); - S32 height = message_in.getValueS32( "height" ); - S32 texture_width = message_in.getValueS32( "texture_width" ); - S32 texture_height = message_in.getValueS32( "texture_height" ); - - if ( ! name.empty() ) - { - // Find the shared memory region with this name - SharedSegmentMap::iterator iter = mSharedSegments.find( name ); - if ( iter != mSharedSegments.end() ) - { - mPixels = ( unsigned char* )iter->second.mAddress; - mWidth = width; - mHeight = height; - - mTextureWidth = texture_width; - mTextureHeight = texture_height; - - init(); - }; - }; - - LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response" ); - message.setValue( "name", name ); - message.setValueS32( "width", width ); - message.setValueS32( "height", height ); - message.setValueS32( "texture_width", texture_width ); - message.setValueS32( "texture_height", texture_height ); - sendMessage( message ); - } - else - if ( message_name == "load_uri" ) - { - std::string uri = message_in.getValue( "uri" ); - if ( ! uri.empty() ) - { - }; - } - else - if ( message_name == "mouse_event" ) - { - std::string event = message_in.getValue( "event" ); - S32 button = message_in.getValueS32( "button" ); - - // left mouse button - if ( button == 0 ) - { - int mouse_x = message_in.getValueS32( "x" ); - int mouse_y = message_in.getValueS32( "y" ); - std::string modifiers = message_in.getValue( "modifiers" ); - - if ( event == "move" ) - { - if ( mMouseButtonDown ) - write_pixel( mouse_x, mouse_y, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80, rand() % 0x80 + 0x80 ); - } - else - if ( event == "down" ) - { - mMouseButtonDown = true; - } - else - if ( event == "up" ) - { - mMouseButtonDown = false; - } - else - if ( event == "double_click" ) - { - }; - }; - } - else - if ( message_name == "key_event" ) - { - std::string event = message_in.getValue( "event" ); - S32 key = message_in.getValueS32( "key" ); - std::string modifiers = message_in.getValue( "modifiers" ); - - if ( event == "down" ) - { - if ( key == ' ') - { - mLastUpdateTime = 0; - update( 0.0f ); - }; - }; - } - else - { - //std::cerr << "MediaPluginExample::receiveMessage: unknown media message: " << message_string << std::endl; - }; - } - else - if ( message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER ) - { - if ( message_name == "browse_reload" ) - { - mLastUpdateTime = 0; - mFirstTime = true; - mStopAction = false; - update( 0.0f ); - } - else - if ( message_name == "browse_stop" ) - { - for( int n = 0; n < ENumObjects; ++n ) - mXInc[ n ] = mYInc[ n ] = 0; - - mStopAction = true; - update( 0.0f ); - } - else - { - //std::cerr << "MediaPluginExample::receiveMessage: unknown media_browser message: " << message_string << std::endl; - }; - } - else - { - //std::cerr << "MediaPluginExample::receiveMessage: unknown message class: " << message_class << std::endl; - }; - }; +// std::cerr << "MediaPluginWebKit::receiveMessage: received message: \"" << message_string << "\"" << std::endl; + LLPluginMessage message_in; + + if(message_in.parse(message_string) >= 0) + { + std::string message_class = message_in.getClass(); + std::string message_name = message_in.getName(); + if(message_class == LLPLUGIN_MESSAGE_CLASS_BASE) + { + if(message_name == "init") + { + LLPluginMessage message("base", "init_response"); + LLSD versions = LLSD::emptyMap(); + versions[LLPLUGIN_MESSAGE_CLASS_BASE] = LLPLUGIN_MESSAGE_CLASS_BASE_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA] = LLPLUGIN_MESSAGE_CLASS_MEDIA_VERSION; + versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION; + message.setValueLLSD("versions", versions); + + std::string plugin_version = "Example plugin 1.0..0"; + message.setValue("plugin_version", plugin_version); + sendMessage(message); + } + else if(message_name == "idle") + { + // no response is necessary here. + F64 time = message_in.getValueReal("time"); + + // Convert time to milliseconds for update() + update((int)(time * 1000.0f)); + } + else if(message_name == "cleanup") + { + } + else if(message_name == "shm_added") + { + SharedSegmentInfo info; + info.mAddress = message_in.getValuePointer("address"); + info.mSize = (size_t)message_in.getValueS32("size"); + std::string name = message_in.getValue("name"); + + mSharedSegments.insert(SharedSegmentMap::value_type(name, info)); + + } + else if(message_name == "shm_remove") + { + std::string name = message_in.getValue("name"); + + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + if(mPixels == iter->second.mAddress) + { + // This is the currently active pixel buffer. Make sure we stop drawing to it. + mPixels = NULL; + mTextureSegmentName.clear(); + } + mSharedSegments.erase(iter); + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown shared memory region!" << std::endl; + } + + // Send the response so it can be cleaned up. + LLPluginMessage message("base", "shm_remove_response"); + message.setValue("name", name); + sendMessage(message); + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown base message: " << message_name << std::endl; + } + } + else if(message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA) + { + if(message_name == "init") + { + // Plugin gets to decide the texture parameters to use. + mDepth = 4; + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params"); + message.setValueS32("default_width", 1024); + message.setValueS32("default_height", 1024); + message.setValueS32("depth", mDepth); + message.setValueU32("internalformat", GL_RGBA); + message.setValueU32("format", GL_RGBA); + message.setValueU32("type", GL_UNSIGNED_BYTE); + message.setValueBoolean("coords_opengl", true); + sendMessage(message); + } + else if(message_name == "size_change") + { + std::string name = message_in.getValue("name"); + S32 width = message_in.getValueS32("width"); + S32 height = message_in.getValueS32("height"); + S32 texture_width = message_in.getValueS32("texture_width"); + S32 texture_height = message_in.getValueS32("texture_height"); + + if(!name.empty()) + { + // Find the shared memory region with this name + SharedSegmentMap::iterator iter = mSharedSegments.find(name); + if(iter != mSharedSegments.end()) + { + mPixels = (unsigned char*)iter->second.mAddress; + mWidth = width; + mHeight = height; + + mTextureWidth = texture_width; + mTextureHeight = texture_height; + }; + }; + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "size_change_response"); + message.setValue("name", name); + message.setValueS32("width", width); + message.setValueS32("height", height); + message.setValueS32("texture_width", texture_width); + message.setValueS32("texture_height", texture_height); + sendMessage(message); + + } + else if(message_name == "load_uri") + { + } + else if(message_name == "mouse_event") + { + std::string event = message_in.getValue("event"); + if(event == "down") + { + + } + else if(event == "up") + { + } + else if(event == "double_click") + { + } + } + } + else + { +// std::cerr << "MediaPluginWebKit::receiveMessage: unknown message class: " << message_class << std::endl; + }; + } } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginExample::write_pixel( int x, int y, unsigned char r, unsigned char g, unsigned char b ) { - // make sure we don't write outside the buffer - if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) ) - return; - - if ( mBackgroundPixels != NULL ) - { - unsigned char *pixel = mBackgroundPixels; - pixel += y * mWidth * mDepth; - pixel += ( x * mDepth ); - pixel[ 0 ] = b; - pixel[ 1 ] = g; - pixel[ 2 ] = r; - - setDirty( x, y, x + 1, y + 1 ); - }; + // make sure we don't write outside the buffer + if ( ( x < 0 ) || ( x >= mWidth ) || ( y < 0 ) || ( y >= mHeight ) ) + return; + + if ( mBackgroundPixels != NULL ) + { + unsigned char *pixel = mBackgroundPixels; + pixel += y * mWidth * mDepth; + pixel += ( x * mDepth ); + pixel[ 0 ] = b; + pixel[ 1 ] = g; + pixel[ 2 ] = r; + + setDirty( x, y, x + 1, y + 1 ); + }; } //////////////////////////////////////////////////////////////////////////////// // void MediaPluginExample::update( F64 milliseconds ) { - if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 ) - return; - - if ( mPixels == 0 ) - return; - - if ( mFirstTime ) - { - for( int n = 0; n < ENumObjects; ++n ) - { - mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 ); - mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 ); - - mColorR[ n ] = rand() % 0x60 + 0x60; - mColorG[ n ] = rand() % 0x60 + 0x60; - mColorB[ n ] = rand() % 0x60 + 0x60; - - mXInc[ n ] = 0; - while ( mXInc[ n ] == 0 ) - mXInc[ n ] = rand() % 7 - 3; - - mYInc[ n ] = 0; - while ( mYInc[ n ] == 0 ) - mYInc[ n ] = rand() % 9 - 4; - - mBlockSize[ n ] = rand() % 0x30 + 0x10; - }; - - delete [] mBackgroundPixels; - - mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ]; - - mFirstTime = false; - }; - - if ( mStopAction ) - return; - - if ( time( NULL ) > mLastUpdateTime + 3 ) - { - const int num_squares = rand() % 20 + 4; - int sqr1_r = rand() % 0x80 + 0x20; - int sqr1_g = rand() % 0x80 + 0x20; - int sqr1_b = rand() % 0x80 + 0x20; - int sqr2_r = rand() % 0x80 + 0x20; - int sqr2_g = rand() % 0x80 + 0x20; - int sqr2_b = rand() % 0x80 + 0x20; - - for ( int y1 = 0; y1 < num_squares; ++y1 ) - { - for ( int x1 = 0; x1 < num_squares; ++x1 ) - { - int px_start = mWidth * x1 / num_squares; - int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares; - int py_start = mHeight * y1 / num_squares; - int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares; - - for( int y2 = py_start; y2 < py_end; ++y2 ) - { - for( int x2 = px_start; x2 < px_end; ++x2 ) - { - int rowspan = mWidth * mDepth; - - if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) - { - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b; - } - else - { - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g; - mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b; - }; - }; - }; - }; - }; - - time( &mLastUpdateTime ); - }; - - memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth ); - - for( int n = 0; n < ENumObjects; ++n ) - { - if ( rand() % 50 == 0 ) - { - mXInc[ n ] = 0; - while ( mXInc[ n ] == 0 ) - mXInc[ n ] = rand() % 7 - 3; - - mYInc[ n ] = 0; - while ( mYInc[ n ] == 0 ) - mYInc[ n ] = rand() % 9 - 4; - }; - - if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] ) - mXInc[ n ] =- mXInc[ n ]; - - if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] ) - mYInc[ n ] =- mYInc[ n ]; - - mXpos[ n ] += mXInc[ n ]; - mYpos[ n ] += mYInc[ n ]; - - for( int y = 0; y < mBlockSize[ n ]; ++y ) - { - for( int x = 0; x < mBlockSize[ n ]; ++x ) - { - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ]; - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ]; - mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ]; - }; - }; - }; - - setDirty( 0, 0, mWidth, mHeight ); + if ( mWidth < 1 || mWidth > 2048 || mHeight < 1 || mHeight > 2048 ) + return; + + if ( mPixels == 0 ) + return; + + if ( mFirstTime ) + { + for( int n = 0; n < ENumObjects; ++n ) + { + mXpos[ n ] = ( mWidth / 2 ) + rand() % ( mWidth / 16 ) - ( mWidth / 32 ); + mYpos[ n ] = ( mHeight / 2 ) + rand() % ( mHeight / 16 ) - ( mHeight / 32 ); + + mColorR[ n ] = rand() % 0x60 + 0x60; + mColorG[ n ] = rand() % 0x60 + 0x60; + mColorB[ n ] = rand() % 0x60 + 0x60; + + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + + mBlockSize[ n ] = rand() % 0x30 + 0x10; + }; + + delete [] mBackgroundPixels; + + mBackgroundPixels = new unsigned char[ mWidth * mHeight * mDepth ]; + + mFirstTime = false; + }; + + if ( mStopAction ) + return; + + if ( time( NULL ) > mLastUpdateTime + 3 ) + { + const int num_squares = rand() % 20 + 4; + int sqr1_r = rand() % 0x80 + 0x20; + int sqr1_g = rand() % 0x80 + 0x20; + int sqr1_b = rand() % 0x80 + 0x20; + int sqr2_r = rand() % 0x80 + 0x20; + int sqr2_g = rand() % 0x80 + 0x20; + int sqr2_b = rand() % 0x80 + 0x20; + + for ( int y1 = 0; y1 < num_squares; ++y1 ) + { + for ( int x1 = 0; x1 < num_squares; ++x1 ) + { + int px_start = mWidth * x1 / num_squares; + int px_end = ( mWidth * ( x1 + 1 ) ) / num_squares; + int py_start = mHeight * y1 / num_squares; + int py_end = ( mHeight * ( y1 + 1 ) ) / num_squares; + + for( int y2 = py_start; y2 < py_end; ++y2 ) + { + for( int x2 = px_start; x2 < px_end; ++x2 ) + { + int rowspan = mWidth * mDepth; + + if ( ( y1 % 2 ) ^ ( x1 % 2 ) ) + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr1_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr1_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr1_b; + } + else + { + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 0 ] = sqr2_r; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 1 ] = sqr2_g; + mBackgroundPixels[ y2 * rowspan + x2 * mDepth + 2 ] = sqr2_b; + }; + }; + }; + }; + }; + + time( &mLastUpdateTime ); + }; + + memcpy( mPixels, mBackgroundPixels, mWidth * mHeight * mDepth ); + + for( int n = 0; n < ENumObjects; ++n ) + { + if ( rand() % 50 == 0 ) + { + mXInc[ n ] = 0; + while ( mXInc[ n ] == 0 ) + mXInc[ n ] = rand() % 7 - 3; + + mYInc[ n ] = 0; + while ( mYInc[ n ] == 0 ) + mYInc[ n ] = rand() % 9 - 4; + }; + + if ( mXpos[ n ] + mXInc[ n ] < 0 || mXpos[ n ] + mXInc[ n ] >= mWidth - mBlockSize[ n ] ) + mXInc[ n ] =- mXInc[ n ]; + + if ( mYpos[ n ] + mYInc[ n ] < 0 || mYpos[ n ] + mYInc[ n ] >= mHeight - mBlockSize[ n ] ) + mYInc[ n ] =- mYInc[ n ]; + + mXpos[ n ] += mXInc[ n ]; + mYpos[ n ] += mYInc[ n ]; + + for( int y = 0; y < mBlockSize[ n ]; ++y ) + { + for( int x = 0; x < mBlockSize[ n ]; ++x ) + { + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 0 ] = mColorR[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 1 ] = mColorG[ n ]; + mPixels[ ( mXpos[ n ] + x ) * mDepth + ( mYpos[ n ] + y ) * mDepth * mWidth + 2 ] = mColorB[ n ]; + }; + }; + }; + + setDirty( 0, 0, mWidth, mHeight ); }; //////////////////////////////////////////////////////////////////////////////// // bool MediaPluginExample::init() { - LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); - message.setValue( "name", "Example Plugin" ); - sendMessage( message ); + LLPluginMessage message( LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text" ); + message.setValue( "name", "Example Plugin" ); + sendMessage( message ); - return true; + return true; }; //////////////////////////////////////////////////////////////////////////////// // int init_media_plugin( LLPluginInstance::sendMessageFunction host_send_func, - void* host_user_data, - LLPluginInstance::sendMessageFunction *plugin_send_func, - void **plugin_user_data ) + void* host_user_data, + LLPluginInstance::sendMessageFunction *plugin_send_func, + void **plugin_user_data ) { - MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data ); - *plugin_send_func = MediaPluginExample::staticReceiveMessage; - *plugin_user_data = ( void* )self; + MediaPluginExample* self = new MediaPluginExample( host_send_func, host_user_data ); + *plugin_send_func = MediaPluginExample::staticReceiveMessage; + *plugin_user_data = ( void* )self; - return 0; + return 0; } + -- cgit v1.2.3 From ca76c55847cdaabe662c880c4d744916c8ca71ac Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Fri, 3 Dec 2010 12:31:12 -0800 Subject: ESC-211 ESC-222 Viewer/Sim comms and outbound data throttle Cleaned up some of the messaging code that sends the LLSD stats report off to the viewer. Added WARNS-level messages when there's a problem with delivery that will result in a data break. Users probably won't care. Added an outbound data throttle that limits stats to the 10 regions of longest occupancy. Should be a reasonable first cut. --- indra/newview/lltexturefetch.cpp | 75 ++++++++++++++++++++++++++++++++++------ 1 file changed, 65 insertions(+), 10 deletions(-) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index dd84290e90..b46f338303 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include +#include #include "llstl.h" @@ -446,7 +447,7 @@ namespace * . +-----+ * . | * . +-----+ - * . | CP |--> HTTP PUT + * . | CP |--> HTTP POST * . +-----+ * . . * . . @@ -469,7 +470,7 @@ namespace * new region. * TE - Timer Expired. Metrics timer has expired (on the order * of 10 minutes). - * CP - CURL Put + * CP - CURL Post * MSC - Modify Stats Collector. State change in the thread-local * collector. Typically a region change which affects the * global pointers used to find the 'current stats'. @@ -571,11 +572,23 @@ public: /* * Count of POST requests outstanding. We maintain the count * indirectly in the CURL request responder's ctor and dtor and - * use it when determining whether or not to sleep the flag. Can't + * use it when determining whether or not to sleep the thread. Can't * use the LLCurl module's request counter as it isn't thread compatible. */ LLAtomic32 curl_post_request_count = 0; - + +/* + * Examines the merged viewer metrics report and if found to be too long, + * will attempt to truncate it in some reasonable fashion. + * + * @param max_regions Limit of regions allowed in report. + * + * @param metrics Full, merged viewer metrics report. + * + * @returns If data was truncated, returns true. + */ +bool truncate_viewer_metrics(int max_regions, LLSD & metrics); + } // end of anonymous namespace @@ -2128,7 +2141,9 @@ bool LLTextureFetch::runCondition() // private method which is unfortunate. I want to use it directly // but I'm going to have to re-implement the logic here (or change // declarations, which I don't want to do right now). - + // + // Changes here may need to be reflected in getPending(). + bool have_no_commands(false); { LLMutexLock lock(&mQueueMutex); @@ -2139,8 +2154,8 @@ bool LLTextureFetch::runCondition() bool have_no_curl_requests(0 == curl_post_request_count); return ! (have_no_commands - && have_no_curl_requests - && (mRequestQueue.empty() && mIdleThread)); + && have_no_curl_requests + && (mRequestQueue.empty() && mIdleThread)); // From base class } ////////////////////////////////////////////////////////////////////////////// @@ -2840,6 +2855,8 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) { mReportingBreak = true; } + LL_WARNS("Texture") << "Break in metrics stream due to POST failure to metrics collection service. Reason: " + << reason << LL_ENDL; } // virtual @@ -2851,14 +2868,14 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) mReportingStarted = true; } } - private: S32 mExpectedSequence; volatile const S32 & mLiveSequence; volatile bool & mReportingBreak; volatile bool & mReportingStarted; - }; + + }; // class lcl_responder if (! gViewerAssetStatsThread1) return true; @@ -2884,7 +2901,9 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) // Merge the two LLSDs into a single report LLViewerAssetStatsFF::merge_stats(main_stats, thread1_stats); - // *TODO: Consider putting a report size limiter here. + // Limit the size of the stats report if necessary. + thread1_stats["truncated"] = truncate_viewer_metrics(10, thread1_stats); + if (! mCapsURL.empty()) { LLCurlRequest::headers_t headers; @@ -2912,6 +2931,42 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) return true; } + +bool +truncate_viewer_metrics(int max_regions, LLSD & metrics) +{ + static const LLSD::String reg_tag("regions"); + static const LLSD::String duration_tag("duration"); + + LLSD & reg_map(metrics[reg_tag]); + if (reg_map.size() <= max_regions) + { + return false; + } + + // Build map of region hashes ordered by duration + typedef std::multimap reg_ordered_list_t; + reg_ordered_list_t regions_by_duration; + + LLSD::map_const_iterator it_end(reg_map.endMap()); + for (LLSD::map_const_iterator it(reg_map.beginMap()); it_end != it; ++it) + { + LLSD::Integer duration = (it->second)[duration_tag].asInteger(); + regions_by_duration.insert(reg_ordered_list_t::value_type(duration, it->first)); + } + + // Erase excess region reports selecting shortest duration first + reg_ordered_list_t::const_iterator it2_end(regions_by_duration.end()); + reg_ordered_list_t::const_iterator it2(regions_by_duration.begin()); + int limit(regions_by_duration.size() - max_regions); + for (int i(0); i < limit && it2_end != it2; ++i, ++it2) + { + reg_map.erase(it2->second); + } + + return true; +} + } // end of anonymous namespace -- cgit v1.2.3 From 468b44e2831241665e3cc0dfcf358cc2e8d6b389 Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 3 Dec 2010 15:00:32 -0800 Subject: Silly whitespace issue - no code change. --- indra/newview/llfloaterwebcontent.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 31b6c3fc49..b2391cc54c 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -194,15 +194,15 @@ void LLFloaterWebContent::onClose(bool app_quitting) destroy(); } -// virtual -void LLFloaterWebContent::draw() -{ - // this is asychronous so we need to keep checking - getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() ); - getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() ); - - LLFloater::draw(); -} +// virtual +void LLFloaterWebContent::draw() +{ + // this is asychronous so we need to keep checking + getChildView( "back" )->setEnabled( mWebBrowser->canNavigateBack() ); + getChildView( "forward" )->setEnabled( mWebBrowser->canNavigateForward() ); + + LLFloater::draw(); +} // virtual void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) -- cgit v1.2.3 From 6924998e85c5637c190c2c97bb94fa421cc6774e Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 3 Dec 2010 15:02:56 -0800 Subject: SOCIAL-333 FIX Order of buttons on Web content floater is wrong --- .../skins/default/xui/en/floater_web_content.xml | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index 97a7a0e737..d57cfe9cab 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -11,6 +11,7 @@ save_rect="true" auto_tile="true" title="WEB CONTENT" + initial_mime_type="text/html" width="820"> + function="WebContent.Stop" /> + Date: Fri, 3 Dec 2010 15:27:01 -0800 Subject: Fix build break on the mac. --- indra/newview/llweb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llweb.h b/indra/newview/llweb.h index a74d4b6364..dc5958e57f 100644 --- a/indra/newview/llweb.h +++ b/indra/newview/llweb.h @@ -58,7 +58,7 @@ public: static void loadURLExternal(const std::string& url, bool async, const std::string& uuid = LLStringUtil::null); // Explicitly open a Web URL using the Web content floater vs. the more general media browser - static void LLWeb::loadWebURL(const std::string& url, const std::string& target, const std::string& uuid); + static void loadWebURL(const std::string& url, const std::string& target, const std::string& uuid); static void loadWebURLInternal(const std::string &url, const std::string& target, const std::string& uuid); static void loadWebURLInternal(const std::string &url) { loadWebURLInternal(url, LLStringUtil::null, LLStringUtil::null); } -- cgit v1.2.3 From a59c43f1adff35107e59fdfc3016d4329324bbaf Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Fri, 3 Dec 2010 18:34:20 -0500 Subject: ESC-210 Non-active regions were getting extra duration time. Metrics were crediting inactive regions (those not current but contributing to the sample) with additional time at the end of the sample interval. Corrected. --- indra/newview/llviewerassetstats.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index cc41a95893..d798786277 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -240,8 +240,9 @@ LLViewerAssetStats::asLLSD() static const LLSD::String rmean_tag("resp_mean"); const duration_t now = LLViewerAssetStatsFF::get_timestamp(); - LLSD regions = LLSD::emptyMap(); + mCurRegionStats->accumulateTime(now); + LLSD regions = LLSD::emptyMap(); for (PerRegionContainer::iterator it = mRegionStats.begin(); mRegionStats.end() != it; ++it) @@ -253,7 +254,6 @@ LLViewerAssetStats::asLLSD() } PerRegionStats & stats = *it->second; - stats.accumulateTime(now); LLSD reg_stat = LLSD::emptyMap(); -- cgit v1.2.3 From 9dd837f6bb7686213bd204131fb3368e63a55f5e Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 3 Dec 2010 15:35:23 -0800 Subject: SOCIAL-334 FIX Remove link color and action from status bar text in web content window --- indra/newview/skins/default/xui/en/floater_web_content.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index d57cfe9cab..eac1b4e712 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -138,6 +138,8 @@ layout="topleft" left_delta="0" name="statusbartext" + parse_urls="false" + text_color="0.4 0.4 0.4 1" top_pad="5" width="452"/> Date: Fri, 3 Dec 2010 15:47:32 -0800 Subject: SOCIAL-248 FIX Remove HEAD requests from WebKit This change makes LLFloaterWebContent always specify a MIME type of "text/html" when navigating to an URL. This tells the plugin system to skip the MIME type probe (which is what does the HEAD request) and just use the WebKit plugin. This means non-web content (such as QuickTime movies) may not work properly in the web content floater. Hopefully this won't be a problem... --- indra/newview/llfloaterwebcontent.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index b2391cc54c..ed66be165e 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -181,9 +181,10 @@ void LLFloaterWebContent::geometryChanged(S32 x, S32 y, S32 width, S32 height) void LLFloaterWebContent::open_media(const std::string& web_url, const std::string& target) { - mWebBrowser->setHomePageUrl(web_url); + // Specifying a mime type of text/html here causes the plugin system to skip the MIME type probe and just open a browser plugin. + mWebBrowser->setHomePageUrl(web_url, "text/html"); mWebBrowser->setTarget(target); - mWebBrowser->navigateTo(web_url); + mWebBrowser->navigateTo(web_url, "text/html"); set_current_url(web_url); } @@ -324,6 +325,6 @@ void LLFloaterWebContent::onEnterAddress() // (perhaps this test should be for minimum length of a URL) if ( mAddressCombo->getValue().asString().length() > 0 ) { - mWebBrowser->navigateTo( mAddressCombo->getValue().asString() ); + mWebBrowser->navigateTo( mAddressCombo->getValue().asString(), "text/html"); }; } -- cgit v1.2.3 From ddf34b02ab1bf3e1bd175337ca0bd487fa3f8c50 Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 3 Dec 2010 16:29:49 -0800 Subject: SOCIAL-229 FIX (Windows) Fix file uploads (Content-Type header bug Updates Windows version of LLQtWebKit --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index f50088495a..2b3364b70b 100644 --- a/install.xml +++ b/install.xml @@ -995,9 +995,9 @@ anguage Infrstructure (CLI) international standard windows md5sum - 40ee8464da01fde6845b8276dcb4cc0f + be78eb0d9383b8c1787dafb3005c4882 url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101201.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101203.tar.bz2
-- cgit v1.2.3 From 4bdf73e5c2edc09a107829de6ab96abf1645a29a Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Fri, 3 Dec 2010 16:34:00 -0800 Subject: SOCIAL-229 FIX Fix file uploads (Content-Type header bug) This was fixed in the llqtwebkit library, by stripping the Content-Type header out of GET requests in LLNetworkAccessManager::createRequest(). This fix is in changeset b9ec6135a395 in the main llqtwebkit repository. This commit updates the Mac build of llqtwebkit. --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index 2b3364b70b..42604605c4 100644 --- a/install.xml +++ b/install.xml @@ -981,9 +981,9 @@ anguage Infrstructure (CLI) international standard darwin md5sum - c69208572a74df24e910e419fbbbb884 + 3ff731e8da5f6ed7c5f06103aff7050c url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-darwin-qt4.7.1-20101201.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-darwin-qt4.7.1-20101203.tar.bz2 linux -- cgit v1.2.3 From e814db889cd720a111208578b688486f446086ed Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 3 Dec 2010 16:44:23 -0800 Subject: SOCIAL-229 FIX (2nd trY) (Windows) Fix file uploads (Content-Type header bug) Updates Windows version of LLQtWebKit --- install.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install.xml b/install.xml index 2b3364b70b..db68227d34 100644 --- a/install.xml +++ b/install.xml @@ -995,7 +995,7 @@ anguage Infrstructure (CLI) international standard windows md5sum - be78eb0d9383b8c1787dafb3005c4882 + 4c45f2375016a36211ea4891357c321d url http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101203.tar.bz2 -- cgit v1.2.3 From f70545382382182d7a65ff5c1945f9ef9897e196 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Fri, 3 Dec 2010 17:12:35 -0800 Subject: Fix for coding standard violations and build error on windows. --- indra/viewer_components/updater/llupdatedownloader.cpp | 4 +++- indra/viewer_components/updater/llupdaterservice.cpp | 5 +++-- indra/viewer_components/updater/llupdaterservice.h | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 7b0f960ce4..ddc14129c2 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -24,6 +24,9 @@ */ #include "linden_common.h" + +#include "llupdatedownloader.h" + #include #include #include @@ -35,7 +38,6 @@ #include "llsd.h" #include "llsdserialize.h" #include "llthread.h" -#include "llupdatedownloader.h" #include "llupdaterservice.h" diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 92a0a09137..dd93fa2550 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -25,10 +25,11 @@ #include "linden_common.h" +#include "llupdaterservice.h" + #include "llupdatedownloader.h" #include "llevents.h" #include "lltimer.h" -#include "llupdaterservice.h" #include "llupdatechecker.h" #include "llupdateinstaller.h" #include "llversionviewer.h" @@ -419,7 +420,7 @@ void LLUpdaterServiceImpl::downloadError(std::string const & message) event["payload"] = payload; LLEventPumps::instance().obtain("mainlooprepeater").post(event); - setState(LLUpdaterService::ERROR); + setState(LLUpdaterService::FAILURE); } void LLUpdaterServiceImpl::restartTimer(unsigned int seconds) diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 3763fbfde0..8b76a9d1e7 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -63,7 +63,7 @@ public: INSTALLING, UP_TO_DATE, TERMINAL, - ERROR + FAILURE }; LLUpdaterService(); -- cgit v1.2.3 From 2a92d622d710ec4f83b3c9b5568d508067bf7107 Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Mon, 6 Dec 2010 16:42:06 -0800 Subject: CHOP-257 - programmer XUI for update ready to install. One tip, one alert. Rev. by Brad --- indra/newview/llappviewer.cpp | 2 +- indra/newview/skins/default/xui/en/notifications.xml | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 63b2fcefd7..31115a4218 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2396,7 +2396,7 @@ namespace { switch (evt["type"].asInteger()) { case LLUpdaterService::DOWNLOAD_COMPLETE: - LLNotificationsUtil::add("DownloadBackground"); + LLNotificationsUtil::add("DownloadBackgroundDialog"); break; case LLUpdaterService::INSTALL_ERROR: LLNotificationsUtil::add("FailedUpdateInstall"); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 60b876d163..2d635bab76 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2887,12 +2887,29 @@ http://secondlife.com/download. name="okbutton" yestext="OK"/> + An updated version of [APP_NAME] has been downloaded. It will be applied the next time you restart [APP_NAME] + + + + + An updated version of [APP_NAME] has been downloaded. + It will be applied the next time you restart [APP_NAME] + Date: Mon, 6 Dec 2010 17:12:43 -0800 Subject: SOCIAL-342 FIX Rename Web Browser Test option in debug menus to reflect the fact it opens the Media browser --- indra/newview/skins/default/xui/en/menu_login.xml | 2 +- indra/newview/skins/default/xui/en/menu_viewer.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 2f47d4e201..271b688be5 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -176,7 +176,7 @@ parameter="message_critical" /> --> Date: Tue, 7 Dec 2010 10:35:37 -0800 Subject: login instance coordinates with updater service --- indra/newview/llappviewer.cpp | 5 + indra/newview/lllogininstance.cpp | 381 ++++++++++++++++++++- indra/newview/lllogininstance.h | 3 + .../newview/skins/default/xui/en/notifications.xml | 13 + indra/newview/tests/lllogininstance_test.cpp | 38 ++ 5 files changed, 439 insertions(+), 1 deletion(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 63b2fcefd7..f45bc474fc 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -80,6 +80,7 @@ #include "llfeaturemanager.h" #include "llurlmatch.h" #include "lltextutil.h" +#include "lllogininstance.h" #include "llweb.h" #include "llsecondlifeurls.h" @@ -590,10 +591,14 @@ LLAppViewer::LLAppViewer() : setupErrorHandling(); sInstance = this; gLoggedInTime.stop(); + + LLLoginInstance::instance().setUpdaterService(mUpdater.get()); } LLAppViewer::~LLAppViewer() { + LLLoginInstance::instance().setUpdaterService(0); + destroyMainloopTimeout(); // If we got to this destructor somehow, the app didn't hang. diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 52ce932241..f6338ac50e 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -55,12 +55,382 @@ #include "llsecapi.h" #include "llstartup.h" #include "llmachineid.h" +#include "llupdaterservice.h" +#include "llevents.h" +#include "llnotificationsutil.h" +#include "llappviewer.h" + +#include + +namespace { + class MandatoryUpdateMachine { + public: + MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService); + + void start(void); + + private: + class State; + class CheckingForUpdate; + class Error; + class ReadyToInstall; + class StartingUpdaterService; + class WaitingForDownload; + + LLLoginInstance & mLoginInstance; + boost::scoped_ptr mState; + LLUpdaterService & mUpdaterService; + + void setCurrentState(State * newState); + }; + + + class MandatoryUpdateMachine::State { + public: + virtual ~State() {} + virtual void enter(void) {} + virtual void exit(void) {} + }; + + + class MandatoryUpdateMachine::CheckingForUpdate: + public MandatoryUpdateMachine::State + { + public: + CheckingForUpdate(MandatoryUpdateMachine & machine); + + virtual void enter(void); + virtual void exit(void); + + private: + LLTempBoundListener mConnection; + MandatoryUpdateMachine & mMachine; + + bool onEvent(LLSD const & event); + }; + + + class MandatoryUpdateMachine::Error: + public MandatoryUpdateMachine::State + { + public: + Error(MandatoryUpdateMachine & machine); + + virtual void enter(void); + virtual void exit(void); + void onButtonClicked(const LLSD &, const LLSD &); + + private: + MandatoryUpdateMachine & mMachine; + }; + + + class MandatoryUpdateMachine::ReadyToInstall: + public MandatoryUpdateMachine::State + { + public: + ReadyToInstall(MandatoryUpdateMachine & machine); + + virtual void enter(void); + virtual void exit(void); + + private: + MandatoryUpdateMachine & mMachine; + }; + + + class MandatoryUpdateMachine::StartingUpdaterService: + public MandatoryUpdateMachine::State + { + public: + StartingUpdaterService(MandatoryUpdateMachine & machine); + + virtual void enter(void); + virtual void exit(void); + void onButtonClicked(const LLSD & uiform, const LLSD & result); + private: + MandatoryUpdateMachine & mMachine; + }; + + + class MandatoryUpdateMachine::WaitingForDownload: + public MandatoryUpdateMachine::State + { + public: + WaitingForDownload(MandatoryUpdateMachine & machine); + + virtual void enter(void); + virtual void exit(void); + + private: + LLTempBoundListener mConnection; + MandatoryUpdateMachine & mMachine; + + bool onEvent(LLSD const & event); + }; +} static const char * const TOS_REPLY_PUMP = "lllogininstance_tos_callback"; static const char * const TOS_LISTENER_NAME = "lllogininstance_tos"; std::string construct_start_string(); + + +// MandatoryUpdateMachine +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService): + mLoginInstance(loginInstance), + mUpdaterService(updaterService) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::start(void) +{ + llinfos << "starting manditory update machine" << llendl; + + if(mUpdaterService.isChecking()) { + switch(mUpdaterService.getState()) { + case LLUpdaterService::UP_TO_DATE: + mUpdaterService.stopChecking(); + mUpdaterService.startChecking(); + // Fall through. + case LLUpdaterService::INITIAL: + case LLUpdaterService::CHECKING_FOR_UPDATE: + setCurrentState(new CheckingForUpdate(*this)); + break; + case LLUpdaterService::DOWNLOADING: + setCurrentState(new WaitingForDownload(*this)); + break; + case LLUpdaterService::TERMINAL: + if(LLUpdaterService::updateReadyToInstall()) { + setCurrentState(new ReadyToInstall(*this)); + } else { + setCurrentState(new Error(*this)); + } + break; + case LLUpdaterService::ERROR: + setCurrentState(new Error(*this)); + break; + default: + llassert(!"unpossible case"); + break; + } + } else { + setCurrentState(new StartingUpdaterService(*this)); + } +} + + +void MandatoryUpdateMachine::setCurrentState(State * newStatePointer) +{ + { + boost::scoped_ptr newState(newStatePointer); + if(mState != 0) mState->exit(); + mState.swap(newState); + + // Old state will be deleted on exit from this block before the new state + // is entered. + } + if(mState != 0) mState->enter(); +} + + + +// MandatoryUpdateMachine::CheckingForUpdate +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::CheckingForUpdate::CheckingForUpdate(MandatoryUpdateMachine & machine): + mMachine(machine) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::CheckingForUpdate::enter(void) +{ + llinfos << "entering checking for update" << llendl; + + mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()). + listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::CheckingForUpdate::onEvent, this, _1)); +} + + +void MandatoryUpdateMachine::CheckingForUpdate::exit(void) +{ +} + + +bool MandatoryUpdateMachine::CheckingForUpdate::onEvent(LLSD const & event) +{ + if(event["type"].asInteger() == LLUpdaterService::STATE_CHANGE) { + switch(event["state"].asInteger()) { + case LLUpdaterService::DOWNLOADING: + mMachine.setCurrentState(new WaitingForDownload(mMachine)); + break; + case LLUpdaterService::UP_TO_DATE: + case LLUpdaterService::TERMINAL: + case LLUpdaterService::ERROR: + mMachine.setCurrentState(new Error(mMachine)); + break; + case LLUpdaterService::INSTALLING: + llassert(!"can't possibly be installing"); + break; + default: + break; + } + } else { + ; // Ignore. + } + + return false; +} + + + +// MandatoryUpdateMachine::Error +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::Error::Error(MandatoryUpdateMachine & machine): + mMachine(machine) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::Error::enter(void) +{ + llinfos << "entering error" << llendl; + LLNotificationsUtil::add("FailedUpdateInstall", LLSD(), LLSD(), boost::bind(&MandatoryUpdateMachine::Error::onButtonClicked, this, _1, _2)); +} + + +void MandatoryUpdateMachine::Error::exit(void) +{ + LLAppViewer::instance()->forceQuit(); +} + + +void MandatoryUpdateMachine::Error::onButtonClicked(const LLSD &, const LLSD &) +{ + mMachine.setCurrentState(0); +} + + + +// MandatoryUpdateMachine::ReadyToInstall +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::ReadyToInstall::ReadyToInstall(MandatoryUpdateMachine & machine): + mMachine(machine) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::ReadyToInstall::enter(void) +{ + llinfos << "entering ready to install" << llendl; + // Open update ready dialog. +} + + +void MandatoryUpdateMachine::ReadyToInstall::exit(void) +{ + // Restart viewer. +} + + + +// MandatoryUpdateMachine::StartingUpdaterService +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::StartingUpdaterService::StartingUpdaterService(MandatoryUpdateMachine & machine): + mMachine(machine) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::StartingUpdaterService::enter(void) +{ + llinfos << "entering start update service" << llendl; + LLNotificationsUtil::add("UpdaterServiceNotRunning", LLSD(), LLSD(), boost::bind(&MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked, this, _1, _2)); +} + + +void MandatoryUpdateMachine::StartingUpdaterService::exit(void) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked(const LLSD & uiform, const LLSD & result) +{ + if(result["OK_okcancelbuttons"].asBoolean()) { + mMachine.mUpdaterService.startChecking(false); + mMachine.setCurrentState(new CheckingForUpdate(mMachine)); + } else { + LLAppViewer::instance()->forceQuit(); + } +} + + + +// MandatoryUpdateMachine::WaitingForDownload +//----------------------------------------------------------------------------- + + +MandatoryUpdateMachine::WaitingForDownload::WaitingForDownload(MandatoryUpdateMachine & machine): + mMachine(machine) +{ + ; // No op. +} + + +void MandatoryUpdateMachine::WaitingForDownload::enter(void) +{ + llinfos << "entering waiting for download" << llendl; + mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()). + listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::WaitingForDownload::onEvent, this, _1)); +} + + +void MandatoryUpdateMachine::WaitingForDownload::exit(void) +{ +} + + +bool MandatoryUpdateMachine::WaitingForDownload::onEvent(LLSD const & event) +{ + switch(event["type"].asInteger()) { + case LLUpdaterService::DOWNLOAD_COMPLETE: + mMachine.setCurrentState(new ReadyToInstall(mMachine)); + break; + case LLUpdaterService::DOWNLOAD_ERROR: + mMachine.setCurrentState(new Error(mMachine)); + break; + default: + break; + } + + return false; +} + + + +// LLLoginInstance +//----------------------------------------------------------------------------- + + LLLoginInstance::LLLoginInstance() : mLoginModule(new LLLogin()), mNotifications(NULL), @@ -69,7 +439,8 @@ LLLoginInstance::LLLoginInstance() : mSkipOptionalUpdate(false), mAttemptComplete(false), mTransferRate(0.0f), - mDispatcher("LLLoginInstance", "change") + mDispatcher("LLLoginInstance", "change"), + mUpdaterService(0) { mLoginModule->getEventPump().listen("lllogininstance", boost::bind(&LLLoginInstance::handleLoginEvent, this, _1)); @@ -353,6 +724,14 @@ bool LLLoginInstance::handleTOSResponse(bool accepted, const std::string& key) void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) { + if(mandatory) + { + gViewerWindow->setShowProgress(false); + MandatoryUpdateMachine * machine = new MandatoryUpdateMachine(*this, *mUpdaterService); + machine->start(); + return; + } + // store off config state, as we might quit soon gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE); LLUIColorTable::instance().saveUserSettings(); diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 159e05046c..cb1f56a971 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -34,6 +34,7 @@ class LLLogin; class LLEventStream; class LLNotificationsInterface; +class LLUpdaterService; // This class hosts the login module and is used to // negotiate user authentication attempts. @@ -75,6 +76,7 @@ public: typedef boost::function UpdaterLauncherCallback; void setUpdaterLauncher(const UpdaterLauncherCallback& ulc) { mUpdaterLauncher = ulc; } + void setUpdaterService(LLUpdaterService * updaterService) { mUpdaterService = updaterService; } private: void constructAuthParams(LLPointer user_credentials); void updateApp(bool mandatory, const std::string& message); @@ -104,6 +106,7 @@ private: int mLastExecEvent; UpdaterLauncherCallback mUpdaterLauncher; LLEventDispatcher mDispatcher; + LLUpdaterService * mUpdaterService; }; #endif diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 60b876d163..bac1ad18d9 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2887,6 +2887,19 @@ http://secondlife.com/download. name="okbutton" yestext="OK"/> + + +An update is required to log in. May we start the background +updater service to fetch and install the update? + + + functor) { return LLNotificationPtr((LLNotification*)0); } + + +//----------------------------------------------------------------------------- +#include "llupdaterservice.h" + +std::string const & LLUpdaterService::pumpName(void) +{ + static std::string wakka = "wakka wakka wakka"; + return wakka; +} +bool LLUpdaterService::updateReadyToInstall(void) { return false; } +void LLUpdaterService::initialize(const std::string& protocol_version, + const std::string& url, + const std::string& path, + const std::string& channel, + const std::string& version) {} + +void LLUpdaterService::setCheckPeriod(unsigned int seconds) {} +void LLUpdaterService::startChecking(bool install_if_ready) {} +void LLUpdaterService::stopChecking() {} +bool LLUpdaterService::isChecking() { return false; } +LLUpdaterService::eUpdaterState LLUpdaterService::getState() { return INITIAL; } + //----------------------------------------------------------------------------- #include "llnotifications.h" #include "llfloaterreg.h" @@ -435,6 +469,8 @@ namespace tut template<> template<> void lllogininstance_object::test<3>() { + skip(); + set_test_name("Test Mandatory Update User Accepts"); // Part 1 - Mandatory Update, with User accepts response. @@ -462,6 +498,8 @@ namespace tut template<> template<> void lllogininstance_object::test<4>() { + skip(); + set_test_name("Test Mandatory Update User Decline"); // Test connect with update needed. -- cgit v1.2.3 From 6faefa6440e61ade7dae9845757756521be92d7a Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 7 Dec 2010 13:14:53 -0800 Subject: show progress bar while downloading update. --- indra/newview/lllogininstance.cpp | 28 +++++++++++++++++++++++++--- indra/newview/tests/lllogininstance_test.cpp | 7 +++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index f6338ac50e..3ff1487286 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -49,6 +49,7 @@ #include "llnotifications.h" #include "llwindow.h" #include "llviewerwindow.h" +#include "llprogressview.h" #if LL_LINUX || LL_SOLARIS #include "lltrans.h" #endif @@ -105,6 +106,7 @@ namespace { private: LLTempBoundListener mConnection; MandatoryUpdateMachine & mMachine; + LLProgressView * mProgressView; bool onEvent(LLSD const & event); }; @@ -165,6 +167,7 @@ namespace { private: LLTempBoundListener mConnection; MandatoryUpdateMachine & mMachine; + LLProgressView * mProgressView; bool onEvent(LLSD const & event); }; @@ -213,7 +216,7 @@ void MandatoryUpdateMachine::start(void) setCurrentState(new Error(*this)); } break; - case LLUpdaterService::ERROR: + case LLUpdaterService::FAILURE: setCurrentState(new Error(*this)); break; default: @@ -256,6 +259,11 @@ void MandatoryUpdateMachine::CheckingForUpdate::enter(void) { llinfos << "entering checking for update" << llendl; + mProgressView = gViewerWindow->getProgressView(); + mProgressView->setMessage("Looking for update..."); + mProgressView->setText("Update"); + mProgressView->setPercent(0); + mProgressView->setVisible(true); mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()). listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::CheckingForUpdate::onEvent, this, _1)); } @@ -275,7 +283,8 @@ bool MandatoryUpdateMachine::CheckingForUpdate::onEvent(LLSD const & event) break; case LLUpdaterService::UP_TO_DATE: case LLUpdaterService::TERMINAL: - case LLUpdaterService::ERROR: + case LLUpdaterService::FAILURE: + mProgressView->setVisible(false); mMachine.setCurrentState(new Error(mMachine)); break; case LLUpdaterService::INSTALLING: @@ -390,7 +399,8 @@ void MandatoryUpdateMachine::StartingUpdaterService::onButtonClicked(const LLSD MandatoryUpdateMachine::WaitingForDownload::WaitingForDownload(MandatoryUpdateMachine & machine): - mMachine(machine) + mMachine(machine), + mProgressView(0) { ; // No op. } @@ -399,6 +409,11 @@ MandatoryUpdateMachine::WaitingForDownload::WaitingForDownload(MandatoryUpdateMa void MandatoryUpdateMachine::WaitingForDownload::enter(void) { llinfos << "entering waiting for download" << llendl; + mProgressView = gViewerWindow->getProgressView(); + mProgressView->setMessage("Downloading update..."); + mProgressView->setText("Update"); + mProgressView->setPercent(0); + mProgressView->setVisible(true); mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()). listen("MandatoryUpdateMachine::CheckingForUpdate", boost::bind(&MandatoryUpdateMachine::WaitingForDownload::onEvent, this, _1)); } @@ -406,6 +421,7 @@ void MandatoryUpdateMachine::WaitingForDownload::enter(void) void MandatoryUpdateMachine::WaitingForDownload::exit(void) { + mProgressView->setVisible(false); } @@ -418,6 +434,12 @@ bool MandatoryUpdateMachine::WaitingForDownload::onEvent(LLSD const & event) case LLUpdaterService::DOWNLOAD_ERROR: mMachine.setCurrentState(new Error(mMachine)); break; + case LLUpdaterService::PROGRESS: { + double downloadSize = event["download_size"].asReal(); + double bytesDownloaded = event["bytes_downloaded"].asReal(); + mProgressView->setPercent(100. * bytesDownloaded / downloadSize); + break; + } default: break; } diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index c906b71c37..5f73aa1d3c 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -68,6 +68,7 @@ static bool gDisconnectCalled = false; #include "../llviewerwindow.h" void LLViewerWindow::setShowProgress(BOOL show) {} +LLProgressView * LLViewerWindow::getProgressView(void) const { return 0; } LLViewerWindow* gViewerWindow; @@ -232,6 +233,12 @@ LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, return NULL; } +//---------------------------------------------------------------------------- +#include "../llprogressview.h" +void LLProgressView::setText(std::string const &){} +void LLProgressView::setPercent(float){} +void LLProgressView::setMessage(std::string const &){} + //----------------------------------------------------------------------------- // LLNotifications class MockNotifications : public LLNotificationsInterface -- cgit v1.2.3 From 4d861ef022f6c22837de4c76ee3e7f2b191b8a5e Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 7 Dec 2010 14:32:37 -0800 Subject: push required flag into download data for later use. --- indra/viewer_components/updater/llupdatedownloader.cpp | 13 +++++++------ indra/viewer_components/updater/llupdatedownloader.h | 3 ++- indra/viewer_components/updater/llupdaterservice.cpp | 4 ++-- .../updater/tests/llupdaterservice_test.cpp | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index ddc14129c2..ce6b488ecb 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -48,7 +48,7 @@ public: Implementation(LLUpdateDownloader::Client & client); ~Implementation(); void cancel(void); - void download(LLURI const & uri, std::string const & hash); + void download(LLURI const & uri, std::string const & hash, bool required); bool isDownloading(void); size_t onHeader(void * header, size_t size); size_t onBody(void * header, size_t size); @@ -118,9 +118,9 @@ void LLUpdateDownloader::cancel(void) } -void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash) +void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash, bool required) { - mImplementation->download(uri, hash); + mImplementation->download(uri, hash, required); } @@ -199,12 +199,13 @@ void LLUpdateDownloader::Implementation::cancel(void) } -void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash) +void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash, bool required) { if(isDownloading()) mClient.downloadError("download in progress"); mDownloadRecordPath = downloadMarkerPath(); mDownloadData = LLSD(); + mDownloadData["required"] = required; try { startDownloading(uri, hash); } catch(DownloadError const & e) { @@ -250,12 +251,12 @@ void LLUpdateDownloader::Implementation::resume(void) resumeDownloading(fileStatus.st_size); } else if(!validateDownload()) { LLFile::remove(filePath); - download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString()); + download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), mDownloadData["required"].asBoolean()); } else { mClient.downloadComplete(mDownloadData); } } else { - download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString()); + download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), mDownloadData["required"].asBoolean()); } } catch(DownloadError & e) { mClient.downloadError(e.what()); diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h index 1b3d7480fd..09ea1676d5 100644 --- a/indra/viewer_components/updater/llupdatedownloader.h +++ b/indra/viewer_components/updater/llupdatedownloader.h @@ -52,7 +52,7 @@ public: void cancel(void); // Start a new download. - void download(LLURI const & uri, std::string const & hash); + void download(LLURI const & uri, std::string const & hash, bool required=false); // Returns true if a download is in progress. bool isDownloading(void); @@ -76,6 +76,7 @@ public: // url - source (remote) location // hash - the md5 sum that should match the installer file. // path - destination (local) location + // required - boolean indicating if this is a required update. // size - the size of the installer in bytes virtual void downloadComplete(LLSD const & data) = 0; diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index dd93fa2550..7d180ff649 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -355,7 +355,7 @@ void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion, { stopTimer(); mIsDownloading = true; - mUpdateDownloader.download(uri, hash); + mUpdateDownloader.download(uri, hash, false); setState(LLUpdaterService::DOWNLOADING); } @@ -366,7 +366,7 @@ void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion, { stopTimer(); mIsDownloading = true; - mUpdateDownloader.download(uri, hash); + mUpdateDownloader.download(uri, hash, true); setState(LLUpdaterService::DOWNLOADING); } diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 04ed4e6364..050bb774f7 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -48,7 +48,7 @@ void LLUpdateChecker::check(std::string const & protocolVersion, std::string con std::string const & servicePath, std::string channel, std::string version) {} LLUpdateDownloader::LLUpdateDownloader(Client & ) {} -void LLUpdateDownloader::download(LLURI const & , std::string const &){} +void LLUpdateDownloader::download(LLURI const & , std::string const &, bool){} class LLDir_Mock : public LLDir { -- cgit v1.2.3 From 3c3683b884542e5aa85099f4ce0c1b556613795d Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 7 Dec 2010 15:41:31 -0800 Subject: limit dowload bandwidth to 'Maximum bandwidth' setting --- indra/newview/llappviewer.cpp | 9 ++++++++ .../updater/llupdatedownloader.cpp | 26 ++++++++++++++++++++++ .../viewer_components/updater/llupdatedownloader.h | 3 +++ .../viewer_components/updater/llupdaterservice.cpp | 11 +++++++++ indra/viewer_components/updater/llupdaterservice.h | 1 + .../updater/tests/llupdaterservice_test.cpp | 1 + 6 files changed, 51 insertions(+) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 08e40168c3..38422621ef 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2413,6 +2413,12 @@ namespace { // let others also handle this event by default return false; } + + bool on_bandwidth_throttle(LLUpdaterService * updater, LLSD const & evt) + { + updater->setBandwidthLimit(evt.asInteger() * (1024/8)); + return false; // Let others receive this event. + }; }; void LLAppViewer::initUpdater() @@ -2435,6 +2441,9 @@ void LLAppViewer::initUpdater() channel, version); mUpdater->setCheckPeriod(check_period); + mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("ThrottleBandwidthKBPS") * (1024/8)); + gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()-> + connect(boost::bind(&on_bandwidth_throttle, mUpdater.get(), _2)); if(gSavedSettings.getBOOL("UpdaterServiceActive")) { bool install_if_ready = true; diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index ce6b488ecb..d67de1c83b 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -54,8 +54,10 @@ public: size_t onBody(void * header, size_t size); int onProgress(double downloadSize, double bytesDownloaded); void resume(void); + void setBandwidthLimit(U64 bytesPerSecond); private: + curl_off_t mBandwidthLimit; bool mCancelled; LLUpdateDownloader::Client & mClient; CURL * mCurl; @@ -136,6 +138,12 @@ void LLUpdateDownloader::resume(void) } +void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) +{ + mImplementation->setBandwidthLimit(bytesPerSecond); +} + + // LLUpdateDownloader::Implementation //----------------------------------------------------------------------------- @@ -170,6 +178,7 @@ namespace { LLUpdateDownloader::Implementation::Implementation(LLUpdateDownloader::Client & client): LLThread("LLUpdateDownloader"), + mBandwidthLimit(0), mCancelled(false), mClient(client), mCurl(0), @@ -264,6 +273,20 @@ void LLUpdateDownloader::Implementation::resume(void) } +void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond) +{ + if((mBandwidthLimit != bytesPerSecond) && isDownloading()) { + llassert(mCurl != 0); + mBandwidthLimit = bytesPerSecond; + CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit); + if(code != CURLE_OK) LL_WARNS("UpdateDownload") << + "unable to change dowload bandwidth" << LL_ENDL; + } else { + mBandwidthLimit = bytesPerSecond; + } +} + + size_t LLUpdateDownloader::Implementation::onHeader(void * buffer, size_t size) { char const * headerPtr = reinterpret_cast (buffer); @@ -388,6 +411,9 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, &progress_callback)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSDATA, this)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOPROGRESS, false)); + if(mBandwidthLimit != 0) { + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, mBandwidthLimit)); + } mDownloadPercent = 0; } diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h index 09ea1676d5..4e20b307b8 100644 --- a/indra/viewer_components/updater/llupdatedownloader.h +++ b/indra/viewer_components/updater/llupdatedownloader.h @@ -60,6 +60,9 @@ public: // Resume a partial download. void resume(void); + // Set a limit on the dowload rate. + void setBandwidthLimit(U64 bytesPerSecond); + private: boost::shared_ptr mImplementation; }; diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 7d180ff649..b29356b968 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -114,6 +114,7 @@ public: const std::string& version); void setCheckPeriod(unsigned int seconds); + void setBandwidthLimit(U64 bytesPerSecond); void startChecking(bool install_if_ready); void stopChecking(); @@ -189,6 +190,11 @@ void LLUpdaterServiceImpl::setCheckPeriod(unsigned int seconds) mCheckPeriod = seconds; } +void LLUpdaterServiceImpl::setBandwidthLimit(U64 bytesPerSecond) +{ + mUpdateDownloader.setBandwidthLimit(bytesPerSecond); +} + void LLUpdaterServiceImpl::startChecking(bool install_if_ready) { if(mUrl.empty() || mChannel.empty() || mVersion.empty()) @@ -541,6 +547,11 @@ void LLUpdaterService::setCheckPeriod(unsigned int seconds) { mImpl->setCheckPeriod(seconds); } + +void LLUpdaterService::setBandwidthLimit(U64 bytesPerSecond) +{ + mImpl->setBandwidthLimit(bytesPerSecond); +} void LLUpdaterService::startChecking(bool install_if_ready) { diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 8b76a9d1e7..1ffa609019 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -76,6 +76,7 @@ public: const std::string& version); void setCheckPeriod(unsigned int seconds); + void setBandwidthLimit(U64 bytesPerSecond); void startChecking(bool install_if_ready = false); void stopChecking(); diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index 050bb774f7..fbdf9a4993 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -101,6 +101,7 @@ std::string LLUpdateDownloader::downloadMarkerPath(void) void LLUpdateDownloader::resume(void) {} void LLUpdateDownloader::cancel(void) {} +void LLUpdateDownloader::setBandwidthLimit(U64 bytesPerSecond) {} int ll_install_update(std::string const &, std::string const &, LLInstallScriptMode) { -- cgit v1.2.3 From 337f95f8b92d5efd0aaf4e955244ddbeae437bf1 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 7 Dec 2010 16:20:19 -0800 Subject: lamo programmer ui for setting downloader bandwidth limit. --- indra/newview/app_settings/settings.xml | 11 ++++++++ indra/newview/llappviewer.cpp | 4 +-- .../default/xui/en/panel_preferences_setup.xml | 32 ++++++++++++++++++++-- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 7dbb375a20..33a48164b0 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9990,6 +9990,17 @@ Value 500.0 + UpdaterMaximumBandwidth + + Comment + Maximum allowable downstream bandwidth for updater service (kilo bits per second) + Persist + 1 + Type + F32 + Value + 500.0 + ToolTipDelay Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 38422621ef..3943ab0f30 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2441,8 +2441,8 @@ void LLAppViewer::initUpdater() channel, version); mUpdater->setCheckPeriod(check_period); - mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("ThrottleBandwidthKBPS") * (1024/8)); - gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()-> + mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("UpdaterMaximumBandwidth") * (1024/8)); + gSavedSettings.getControl("UpdaterMaximumBandwidth")->getSignal()-> connect(boost::bind(&on_bandwidth_throttle, mUpdater.get(), _2)); if(gSavedSettings.getBOOL("UpdaterServiceActive")) { diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 584bd1ea9d..b551901a56 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -142,7 +142,7 @@ layout="topleft" left="80" name="Cache location" - top_delta="40" + top_delta="20" width="300"> Cache location: @@ -341,7 +341,6 @@ name="web_proxy_port" top_delta="0" width="145" /> - - + +Download bandwidth + + -- cgit v1.2.3 From 99488e6db8730189170a36fa2c2e7621e666868d Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Wed, 8 Dec 2010 09:39:14 -0800 Subject: fix windows build. --- indra/newview/tests/lllogininstance_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 5f73aa1d3c..59a8e40607 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -40,6 +40,7 @@ #if defined(LL_WINDOWS) #pragma warning(disable: 4355) // using 'this' in base-class ctor initializer expr +#pragma warning(disable: 4702) // disable 'unreachable code' so we can safely use skip(). #endif // Constants -- cgit v1.2.3 From 115851ce14b7aff83027f9d4d2ec32b3ce448c56 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Wed, 8 Dec 2010 13:11:19 -0800 Subject: improved dialog message for required update. --- indra/newview/skins/default/xui/en/notifications.xml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e333c891a4..e32e28bea3 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2892,12 +2892,11 @@ http://secondlife.com/download. icon="alertmodal.tga" name="UpdaterServiceNotRunning" type="alertmodal"> -An update is required to log in. May we start the background -updater service to fetch and install the update? +There is a required update for your Second Life Installation. + notext="Quit Second Life" + yestext="Download and install now"/> Date: Wed, 8 Dec 2010 13:59:45 -0800 Subject: progress viewer will no longer fade out if toggled quickly from visible to invisible to visible again. --- indra/newview/llprogressview.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index e9504cbba0..250dfc5713 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -133,13 +133,13 @@ void LLProgressView::setVisible(BOOL visible) mFadeTimer.start(); } // showing progress view - else if (!getVisible() && visible) + else if (visible && (!getVisible() || mFadeTimer.getStarted())) { setFocus(TRUE); mFadeTimer.stop(); mProgressTimer.start(); LLPanel::setVisible(TRUE); - } + } } -- cgit v1.2.3 From 61b675e0afb96d1d46b1f36a8d54bb8146ef27d6 Mon Sep 17 00:00:00 2001 From: callum Date: Wed, 8 Dec 2010 14:38:20 -0800 Subject: SOCIAL-358 FIX Add button to Web Content floater to open current URL in system browser --- indra/newview/llfloaterwebcontent.cpp | 22 ++++++++++++++++++---- indra/newview/llfloaterwebcontent.h | 2 +- .../skins/default/xui/en/floater_web_content.xml | 19 ++++++++++++++++++- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index ed66be165e..d9748b2235 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -33,6 +33,7 @@ #include "llprogressbar.h" #include "lltextbox.h" #include "llviewercontrol.h" +#include "llweb.h" #include "llwindow.h" #include "llfloaterwebcontent.h" @@ -43,8 +44,8 @@ LLFloaterWebContent::LLFloaterWebContent( const LLSD& key ) mCommitCallbackRegistrar.add( "WebContent.Back", boost::bind( &LLFloaterWebContent::onClickBack, this )); mCommitCallbackRegistrar.add( "WebContent.Forward", boost::bind( &LLFloaterWebContent::onClickForward, this )); mCommitCallbackRegistrar.add( "WebContent.Reload", boost::bind( &LLFloaterWebContent::onClickReload, this )); - mCommitCallbackRegistrar.add( "WebContent.EnterAddress", boost::bind( &LLFloaterWebContent::onEnterAddress, this )); + mCommitCallbackRegistrar.add( "WebContent.PopExternal", boost::bind( &LLFloaterWebContent::onPopExternal, this )); } BOOL LLFloaterWebContent::postBuild() @@ -58,8 +59,9 @@ BOOL LLFloaterWebContent::postBuild() // observe browser events mWebBrowser->addObserver( this ); - // these button are always enabled + // these buttons are always enabled getChildView("reload")->setEnabled( true ); + getChildView("popexternal")->setEnabled( true ); return TRUE; } @@ -323,8 +325,20 @@ void LLFloaterWebContent::onEnterAddress() { // make sure there is at least something there. // (perhaps this test should be for minimum length of a URL) - if ( mAddressCombo->getValue().asString().length() > 0 ) + std::string url = mAddressCombo->getValue().asString(); + if ( url.length() > 0 ) + { + mWebBrowser->navigateTo( url, "text/html"); + }; +} + +void LLFloaterWebContent::onPopExternal() +{ + // make sure there is at least something there. + // (perhaps this test should be for minimum length of a URL) + std::string url = mAddressCombo->getValue().asString(); + if ( url.length() > 0 ) { - mWebBrowser->navigateTo( mAddressCombo->getValue().asString(), "text/html"); + LLWeb::loadURLExternal( url ); }; } diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 1effa2c4ab..09b4945b65 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -61,7 +61,7 @@ public: void onClickReload(); void onClickStop(); void onEnterAddress(); - void onClickGo(); + void onPopExternal(); private: void open_media(const std::string& media_url, const std::string& target); diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index eac1b4e712..3072ca1b0e 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -110,10 +110,27 @@ name="address" combo_editor.select_on_focus="true" top_delta="0" - width="729"> + width="702"> + Date: Wed, 8 Dec 2010 15:54:50 -0800 Subject: Fix for CHOP-262 (update notifications prior to login) and first attempt at CHOP-261 (add handlers for update ready notification buttons) reviewed by mani. --- indra/newview/llappviewer.cpp | 28 ++++++++++++++++++++-- .../newview/skins/default/xui/en/notifications.xml | 4 ++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3943ab0f30..b852b63cf8 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2394,14 +2394,38 @@ bool LLAppViewer::initConfiguration() } namespace { - // *TODO - decide if there's a better place for this function. + // *TODO - decide if there's a better place for these functions. // do we need a file llupdaterui.cpp or something? -brad + + void apply_update_callback(LLSD const & notification, LLSD const & response) + { + lldebugs << "LLUpdate user response: " << response << llendl; + if(response["OK_okcancelbuttons"].asBoolean()) + { + llinfos << "LLUpdate restarting viewer" << llendl; + static const bool install_if_ready = true; + // *HACK - this lets us launch the installer immediately for now + LLUpdaterService().startChecking(install_if_ready); + } + } + bool notify_update(LLSD const & evt) { + std::string notification_name; switch (evt["type"].asInteger()) { case LLUpdaterService::DOWNLOAD_COMPLETE: - LLNotificationsUtil::add("DownloadBackgroundDialog"); + if(LLStartUp::getStartupState() < STATE_STARTED) + { + // CHOP-262 we need to use a different notification + // method prior to login. + notification_name = "DownloadBackgroundDialog"; + } + else + { + notification_name = "DownloadBackgroundTip"; + } + LLNotificationsUtil::add(notification_name, LLSD(), LLSD(), apply_update_callback); break; case LLUpdaterService::INSTALL_ERROR: LLNotificationsUtil::add("FailedUpdateInstall"); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index e333c891a4..8c76231595 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2901,9 +2901,9 @@ updater service to fetch and install the update? + type="notify"> An updated version of [APP_NAME] has been downloaded. It will be applied the next time you restart [APP_NAME] Date: Wed, 8 Dec 2010 21:52:19 -0800 Subject: STORM-524 : Add a click event on the L$ balance so to force refresh its content, modified tooltip to mention this --- indra/newview/llstatusbar.cpp | 18 +++++++++++++++--- indra/newview/llstatusbar.h | 2 ++ .../newview/skins/default/xui/en/panel_status_bar.xml | 2 +- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index e9fc25404a..1b8be7a5b2 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -115,6 +115,7 @@ LLStatusBar::LLStatusBar(const LLRect& rect) mSGBandwidth(NULL), mSGPacketLoss(NULL), mBtnVolume(NULL), + mBoxBalance(NULL), mBalance(0), mHealth(100), mSquareMetersCredit(0), @@ -168,6 +169,9 @@ BOOL LLStatusBar::postBuild() getChild("buyL")->setCommitCallback( boost::bind(&LLStatusBar::onClickBuyCurrency, this)); + mBoxBalance = getChild("balance"); + mBoxBalance->setClickedCallback( &LLStatusBar::onClickBalance, this ); + mBtnVolume = getChild( "volume_btn" ); mBtnVolume->setClickedCallback( onClickVolume, this ); mBtnVolume->setMouseEnterCallback(boost::bind(&LLStatusBar::onMouseEnterVolume, this)); @@ -304,6 +308,7 @@ void LLStatusBar::setVisibleForMouselook(bool visible) { mTextTime->setVisible(visible); getChild("balance_bg")->setVisible(visible); + mBoxBalance->setVisible(visible); mBtnVolume->setVisible(visible); mMediaToggle->setVisible(visible); mSGBandwidth->setVisible(visible); @@ -330,16 +335,15 @@ void LLStatusBar::setBalance(S32 balance) std::string money_str = LLResMgr::getInstance()->getMonetaryString( balance ); - LLTextBox* balance_box = getChild("balance"); LLStringUtil::format_map_t string_args; string_args["[AMT]"] = llformat("%s", money_str.c_str()); std::string label_str = getString("buycurrencylabel", string_args); - balance_box->setValue(label_str); + mBoxBalance->setValue(label_str); // Resize the L$ balance background to be wide enough for your balance plus the buy button { const S32 HPAD = 24; - LLRect balance_rect = balance_box->getTextBoundingRect(); + LLRect balance_rect = mBoxBalance->getTextBoundingRect(); LLRect buy_rect = getChildView("buyL")->getRect(); LLView* balance_bg_view = getChildView("balance_bg"); LLRect balance_bg_rect = balance_bg_view->getRect(); @@ -505,6 +509,14 @@ static void onClickVolume(void* data) LLAppViewer::instance()->setMasterSystemAudioMute(!mute_audio); } +//static +void LLStatusBar::onClickBalance(void* ) +{ + // Force a balance request message: + LLStatusBar::sendMoneyBalanceRequest(); + // The refresh of the display (call to setBalance()) will be done by process_money_balance_reply() +} + //static void LLStatusBar::onClickMediaToggle(void* data) { diff --git a/indra/newview/llstatusbar.h b/indra/newview/llstatusbar.h index 2388aeb0c8..4ea3183d18 100644 --- a/indra/newview/llstatusbar.h +++ b/indra/newview/llstatusbar.h @@ -94,6 +94,7 @@ private: void onClickScreen(S32 x, S32 y); static void onClickMediaToggle(void* data); + static void onClickBalance(void* data); private: LLTextBox *mTextTime; @@ -102,6 +103,7 @@ private: LLStatGraph *mSGPacketLoss; LLButton *mBtnVolume; + LLTextBox *mBoxBalance; LLButton *mMediaToggle; LLView* mScriptOut; LLFrameTimer mClockUpdateTimer; diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index 2f52ca660b..d756dfb7de 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -51,7 +51,7 @@ height="18" left="0" name="balance" - tool_tip="My Balance" + tool_tip="Click to refresh your L$ balance" v_pad="4" top="0" wrap="false" -- cgit v1.2.3 From 0df07ea31afe72b2e30fc061b70b3205925b6107 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Thu, 9 Dec 2010 11:45:24 -0800 Subject: STORM-524 : Add some balance request messages after L$ purchase interaction --- indra/newview/llbuycurrencyhtml.cpp | 4 ++++ indra/newview/llfloaterbuycurrency.cpp | 3 +++ indra/newview/llfloaterbuycurrencyhtml.cpp | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/indra/newview/llbuycurrencyhtml.cpp b/indra/newview/llbuycurrencyhtml.cpp index d35c9ed853..e5a9be0203 100644 --- a/indra/newview/llbuycurrencyhtml.cpp +++ b/indra/newview/llbuycurrencyhtml.cpp @@ -33,6 +33,7 @@ #include "llfloaterreg.h" #include "llcommandhandler.h" #include "llviewercontrol.h" +#include "llstatusbar.h" // support for secondlife:///app/buycurrencyhtml/{ACTION}/{NEXT_ACTION}/{RETURN_CODE} SLapps class LLBuyCurrencyHTMLHandler : @@ -156,4 +157,7 @@ void LLBuyCurrencyHTML::closeDialog() { buy_currency_floater->closeFloater(); }; + + // Update L$ balance in the status bar in case L$ were purchased + LLStatusBar::sendMoneyBalanceRequest(); } diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp index 58c79fdf15..48b00a7964 100644 --- a/indra/newview/llfloaterbuycurrency.cpp +++ b/indra/newview/llfloaterbuycurrency.cpp @@ -261,6 +261,9 @@ void LLFloaterBuyCurrencyUI::updateUI() } getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError); + + // Update L$ balance + LLStatusBar::sendMoneyBalanceRequest(); } void LLFloaterBuyCurrencyUI::onClickBuy() diff --git a/indra/newview/llfloaterbuycurrencyhtml.cpp b/indra/newview/llfloaterbuycurrencyhtml.cpp index bde620d965..e8050c4480 100644 --- a/indra/newview/llfloaterbuycurrencyhtml.cpp +++ b/indra/newview/llfloaterbuycurrencyhtml.cpp @@ -105,7 +105,7 @@ void LLFloaterBuyCurrencyHTML::handleMediaEvent( LLPluginClassMedia* self, EMedi // void LLFloaterBuyCurrencyHTML::onClose( bool app_quitting ) { - // update L$ balanace one more time + // Update L$ balance one more time LLStatusBar::sendMoneyBalanceRequest(); destroy(); -- cgit v1.2.3 From 9a3f6c1e0cb690201f91f21e3be393bace827604 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Thu, 9 Dec 2010 12:49:51 -0800 Subject: change updater settings from check box to drop down menu; add choice of whether to install automatically as well as download automatically (not actually implemented yet). --- indra/newview/app_settings/settings.xml | 8 +-- indra/newview/llappviewer.cpp | 2 +- indra/newview/llviewercontrol.cpp | 4 +- .../default/xui/en/panel_preferences_setup.xml | 73 ++++++++++------------ 4 files changed, 40 insertions(+), 47 deletions(-) diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 33a48164b0..5d89051c45 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11101,16 +11101,16 @@ Value 15 - UpdaterServiceActive + UpdaterServiceSetting Comment - Enable or disable the updater service. + Configure updater service. Persist 1 Type - Boolean + U32 Value - 1 + 3 UpdaterServiceCheckPeriod diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index b852b63cf8..1306e92b35 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2468,7 +2468,7 @@ void LLAppViewer::initUpdater() mUpdater->setBandwidthLimit((int)gSavedSettings.getF32("UpdaterMaximumBandwidth") * (1024/8)); gSavedSettings.getControl("UpdaterMaximumBandwidth")->getSignal()-> connect(boost::bind(&on_bandwidth_throttle, mUpdater.get(), _2)); - if(gSavedSettings.getBOOL("UpdaterServiceActive")) + if(gSavedSettings.getU32("UpdaterServiceSetting")) { bool install_if_ready = true; mUpdater->startChecking(install_if_ready); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 622d09c600..2c75551285 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -504,7 +504,7 @@ bool toggle_show_object_render_cost(const LLSD& newvalue) void toggle_updater_service_active(LLControlVariable* control, const LLSD& new_value) { - if(new_value.asBoolean()) + if(new_value.asInteger()) { LLUpdaterService().startChecking(); } @@ -661,7 +661,7 @@ void settings_setup_listeners() gSavedSettings.getControl("ShowNavbarFavoritesPanel")->getSignal()->connect(boost::bind(&toggle_show_favorites_panel, _2)); gSavedSettings.getControl("ShowMiniLocationPanel")->getSignal()->connect(boost::bind(&toggle_show_mini_location_panel, _2)); gSavedSettings.getControl("ShowObjectRenderingCost")->getSignal()->connect(boost::bind(&toggle_show_object_render_cost, _2)); - gSavedSettings.getControl("UpdaterServiceActive")->getSignal()->connect(&toggle_updater_service_active); + gSavedSettings.getControl("UpdaterServiceSetting")->getSignal()->connect(&toggle_updater_service_active); gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2)); gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2)); } diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index b551901a56..542b6bcf6b 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -341,46 +341,39 @@ name="web_proxy_port" top_delta="0" width="145" /> - -Download bandwidth + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + left="30" + name="Software updates:" + mouse_opaque="false" + top_pad="5" + width="300"> + Software updates: - + + + + + -- cgit v1.2.3 From 90da762f97a30c16e23184352f4d413c34279ba4 Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Thu, 9 Dec 2010 18:04:03 -0800 Subject: CHOP-265 Fixed up LL_SEND_CRASH_REPORTS usage. Reviewed by Brad. --- build.sh | 3 ++- indra/cmake/00-Common.cmake | 27 ++++++++++++++------------- indra/newview/CMakeLists.txt | 40 +++++++++++++++++++++------------------- indra/newview/llappviewer.cpp | 2 ++ 4 files changed, 39 insertions(+), 33 deletions(-) diff --git a/build.sh b/build.sh index f9c6beefed..c5f74c23ee 100755 --- a/build.sh +++ b/build.sh @@ -59,10 +59,11 @@ pre_build() -t $variant \ -G "$cmake_generator" \ configure \ - -DGRID:STRING="$viewer_grid" \ + -DGRID:STRING="$viewer_grid" \ -DVIEWER_CHANNEL:STRING="$viewer_channel" \ -DVIEWER_LOGIN_CHANNEL:STRING="$login_channel" \ -DINSTALL_PROPRIETARY:BOOL=ON \ + -DRELEASE_CRASH_REPORTING:BOOL=ON \ -DLOCALIZESETUP:BOOL=ON \ -DPACKAGE:BOOL=ON \ -DCMAKE_VERBOSE_MAKEFILE:BOOL=TRUE diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index db2cdb5ff8..dbe0cf5cd0 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -4,27 +4,28 @@ include(Variables) - # Portable compilation flags. - -if (EXISTS ${CMAKE_SOURCE_DIR}/llphysics) - # The release build should only offer to send crash reports if we're - # building from a Linden internal source tree. - set(release_crash_reports 1) -else (EXISTS ${CMAKE_SOURCE_DIR}/llphysics) - set(release_crash_reports 0) -endif (EXISTS ${CMAKE_SOURCE_DIR}/llphysics) - set(CMAKE_CXX_FLAGS_DEBUG "-D_DEBUG -DLL_DEBUG=1") set(CMAKE_CXX_FLAGS_RELEASE - "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=${release_crash_reports} -DNDEBUG") + "-DLL_RELEASE=1 -DLL_RELEASE_FOR_DOWNLOAD=1 -D_SECURE_SCL=0 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO - "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DLL_SEND_CRASH_REPORTS=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1") + "-DLL_RELEASE=1 -D_SECURE_SCL=0 -DNDEBUG -DLL_RELEASE_WITH_DEBUG_INFO=1") +# Configure crash reporting +set(RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in release builds") +set(NON_RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in developer builds") -# Don't bother with a MinSizeRel build. +if(RELEASE_CRASH_REPORTING) + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DLL_SEND_CRASH_REPORTS=1") +endif() + +if(NON_RELEASE_CRASH_REPORTING) + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DLL_SEND_CRASH_REPORTS=1") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DLL_SEND_CRASH_REPORTS=1") +endif() +# Don't bother with a MinSizeRel build. set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING "Supported build types." FORCE) diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 679637caf6..1a3f274664 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -1843,29 +1843,31 @@ if (PACKAGE) set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) endif (LINUX) - if(CMAKE_CFG_INTDIR STREQUAL ".") + if(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) + if(CMAKE_CFG_INTDIR STREQUAL ".") set(LLBUILD_CONFIG ${CMAKE_BUILD_TYPE}) - else(CMAKE_CFG_INTDIR STREQUAL ".") + else(CMAKE_CFG_INTDIR STREQUAL ".") # set LLBUILD_CONFIG to be a shell variable evaluated at build time # reflecting the configuration we are currently building. set(LLBUILD_CONFIG ${CMAKE_CFG_INTDIR}) - endif(CMAKE_CFG_INTDIR STREQUAL ".") - add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" - COMMAND "${PYTHON_EXECUTABLE}" - ARGS - "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" - "${LLBUILD_CONFIG}" - "${VIEWER_DIST_DIR}" - "${VIEWER_EXE_GLOBS}" - "${VIEWER_LIB_GLOB}" - "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" - "${VIEWER_SYMBOL_FILE}" - DEPENDS generate_breakpad_symbols.py - VERBATIM - ) - add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}") - add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") - add_dependencies(package generate_breakpad_symbols) + endif(CMAKE_CFG_INTDIR STREQUAL ".") + add_custom_command(OUTPUT "${VIEWER_SYMBOL_FILE}" + COMMAND "${PYTHON_EXECUTABLE}" + ARGS + "${CMAKE_CURRENT_SOURCE_DIR}/generate_breakpad_symbols.py" + "${LLBUILD_CONFIG}" + "${VIEWER_DIST_DIR}" + "${VIEWER_EXE_GLOBS}" + "${VIEWER_LIB_GLOB}" + "${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/bin/dump_syms" + "${VIEWER_SYMBOL_FILE}" + DEPENDS generate_breakpad_symbols.py + VERBATIM) + + add_custom_target(generate_breakpad_symbols DEPENDS "${VIEWER_SYMBOL_FILE}") + add_dependencies(generate_breakpad_symbols "${VIEWER_BINARY_NAME}" "${VIEWER_COPY_MANIFEST}") + add_dependencies(package generate_breakpad_symbols) + endif(RELEASE_CRASH_REPORTING OR NON_RELEASE_CRASH_REPORTING) endif (PACKAGE) if (LL_TESTS) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 6c07974f69..8e16398390 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2858,8 +2858,10 @@ void LLAppViewer::handleViewerCrash() pApp->removeMarkerFile(false); } +#if LL_SEND_CRASH_REPORTS // Call to pure virtual, handled by platform specific llappviewer instance. pApp->handleCrashReporting(); +#endif return; } -- cgit v1.2.3 From 38476e35931fb6f68805dbbae143b7bf6dbd04de Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Fri, 10 Dec 2010 10:09:10 -0500 Subject: See if using a fully-qualified project name helps with the build. --- BuildParams | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/BuildParams b/BuildParams index ba2884ce4e..a61eb2dd15 100644 --- a/BuildParams +++ b/BuildParams @@ -219,6 +219,15 @@ viewer-asset-delivery.viewer_channel = "Second Life Development" viewer-asset-delivery.login_channel = "Second Life Development" viewer-asset-delivery.build_viewer_update_version_manager = false viewer-asset-delivery.email = monty@lindenlab.com +viewer-asset-delivery.build_server = false +viewer-asset-delivery.build_server_tests = false + +viewer-asset-delivery-metrics.viewer_channel = "Second Life Development" +viewer-asset-delivery-metrics.login_channel = "Second Life Development" +viewer-asset-delivery-metrics.build_viewer_update_version_manager = false +viewer-asset-delivery-metrics.email = monty@lindenlab.com +viewer-asset-delivery-metrics.build_server = false +viewer-asset-delivery-metrics.build_server_tests = false # eof -- cgit v1.2.3 From b89b41991e49e24b826d1b44ebfe3587a8b248ab Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Fri, 10 Dec 2010 09:43:01 -0800 Subject: ui improvements to more closely match UX design. --- indra/newview/llappviewer.cpp | 52 +++++++++++++++++++--- indra/newview/lllogininstance.cpp | 8 +++- .../newview/skins/default/xui/en/notifications.xml | 38 +++++++++++++--- indra/newview/tests/lllogininstance_test.cpp | 1 + .../viewer_components/updater/llupdaterservice.cpp | 17 +++++++ indra/viewer_components/updater/llupdaterservice.h | 5 +++ 6 files changed, 107 insertions(+), 14 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 1306e92b35..41be4eb065 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2408,6 +2408,49 @@ namespace { LLUpdaterService().startChecking(install_if_ready); } } + + void apply_update_ok_callback(LLSD const & notification, LLSD const & response) + { + llinfos << "LLUpdate restarting viewer" << llendl; + static const bool install_if_ready = true; + // *HACK - this lets us launch the installer immediately for now + LLUpdaterService().startChecking(install_if_ready); + } + + void on_required_update_downloaded(LLSD const & data) + { + std::string notification_name; + if(LLStartUp::getStartupState() <= STATE_LOGIN_WAIT) + { + // The user never saw the progress bar. + notification_name = "RequiredUpdateDownloadedVerboseDialog"; + } + else + { + notification_name = "RequiredUpdateDownloadedDialog"; + } + LLSD substitutions; + substitutions["VERSION"] = data["version"]; + LLNotificationsUtil::add(notification_name, substitutions, LLSD(), &apply_update_ok_callback); + } + + void on_optional_update_downloaded(LLSD const & data) + { + std::string notification_name; + if(LLStartUp::getStartupState() < STATE_STARTED) + { + // CHOP-262 we need to use a different notification + // method prior to login. + notification_name = "DownloadBackgroundDialog"; + } + else + { + notification_name = "DownloadBackgroundTip"; + } + LLSD substitutions; + substitutions["VERSION"] = data["version"]; + LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_update_callback); + } bool notify_update(LLSD const & evt) { @@ -2415,17 +2458,14 @@ namespace { switch (evt["type"].asInteger()) { case LLUpdaterService::DOWNLOAD_COMPLETE: - if(LLStartUp::getStartupState() < STATE_STARTED) + if(evt["required"].asBoolean()) { - // CHOP-262 we need to use a different notification - // method prior to login. - notification_name = "DownloadBackgroundDialog"; + on_required_update_downloaded(evt); } else { - notification_name = "DownloadBackgroundTip"; + on_optional_update_downloaded(evt); } - LLNotificationsUtil::add(notification_name, LLSD(), LLSD(), apply_update_callback); break; case LLUpdaterService::INSTALL_ERROR: LLNotificationsUtil::add("FailedUpdateInstall"); diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 3ff1487286..1858cbdcd9 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -62,6 +62,7 @@ #include "llappviewer.h" #include +#include namespace { class MandatoryUpdateMachine { @@ -261,7 +262,7 @@ void MandatoryUpdateMachine::CheckingForUpdate::enter(void) mProgressView = gViewerWindow->getProgressView(); mProgressView->setMessage("Looking for update..."); - mProgressView->setText("Update"); + mProgressView->setText("There is a required update for your Second Life installation."); mProgressView->setPercent(0); mProgressView->setVisible(true); mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()). @@ -411,7 +412,10 @@ void MandatoryUpdateMachine::WaitingForDownload::enter(void) llinfos << "entering waiting for download" << llendl; mProgressView = gViewerWindow->getProgressView(); mProgressView->setMessage("Downloading update..."); - mProgressView->setText("Update"); + std::ostringstream stream; + stream << "There is a required update for your Second Life installation." << std::endl << + "Version " << mMachine.mUpdaterService.updatedVersion(); + mProgressView->setText(stream.str()); mProgressView->setPercent(0); mProgressView->setVisible(true); mConnection = LLEventPumps::instance().obtain(LLUpdaterService::pumpName()). diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 80a210f9bc..eecbeeb8dc 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2893,6 +2893,9 @@ http://secondlife.com/download. 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. -An updated version of [APP_NAME] has been downloaded. -It will be applied the next time you restart [APP_NAME] +We have downloaded and update to your [APP_NAME] installation. +Version [VERSION] - An updated version of [APP_NAME] has been downloaded. - It will be applied the next time you restart [APP_NAME] +We have downloaded and update to your [APP_NAME] installation. +Version [VERSION] + notext="Later..." + yestext="Install now and restart [APP_NAME]"/> + + + +We have downloaded a required software update. +Version [VERSION] + +We must restart [APP_NAME] to install the update. + + + + +We must restart [APP_NAME] to install the update. + setAppExitCallback(aecb); } +std::string LLUpdaterService::updatedVersion(void) +{ + return mImpl->updatedVersion(); +} + std::string const & ll_get_version(void) { static std::string version(""); diff --git a/indra/viewer_components/updater/llupdaterservice.h b/indra/viewer_components/updater/llupdaterservice.h index 1ffa609019..421481bc43 100644 --- a/indra/viewer_components/updater/llupdaterservice.h +++ b/indra/viewer_components/updater/llupdaterservice.h @@ -90,6 +90,11 @@ public: app_exit_callback_t aecb = callable; setImplAppExitCallback(aecb); } + + // If an update is or has been downloaded, this method will return the + // version string for that update. An empty string will be returned + // otherwise. + std::string updatedVersion(void); private: boost::shared_ptr mImpl; -- cgit v1.2.3 From 8044661bd581fd7b6a25bd04d4c4f7e32e421faf Mon Sep 17 00:00:00 2001 From: Richard Linden Date: Fri, 10 Dec 2010 10:11:03 -0800 Subject: WIP XUI HTTP Auth dialog refactored LLWindowShade into seperate file improved layout of dialog improved dialog resizing logic Tab and Enter keys now work as expected in windowshade form added "modal" capability to window shade added HTTP Auth notifications to MOAP --- indra/llui/CMakeLists.txt | 2 + indra/llui/lllayoutstack.h | 3 + indra/llui/lluictrl.cpp | 2 +- indra/llui/llview.h | 9 +- indra/llui/llwindowshade.cpp | 328 ++++++++++++++++++++++ indra/llui/llwindowshade.h | 69 +++++ indra/newview/llbrowsernotification.cpp | 12 +- indra/newview/llmediactrl.cpp | 280 +----------------- indra/newview/llmediactrl.h | 1 - indra/newview/llpanelprimmediacontrols.cpp | 60 +++- indra/newview/llpanelprimmediacontrols.h | 8 + indra/newview/llviewermedia.cpp | 43 ++- indra/newview/llviewermedia.h | 12 +- indra/newview/llviewermediafocus.cpp | 2 +- indra/newview/skins/default/xui/en/menu_login.xml | 1 - 15 files changed, 546 insertions(+), 286 deletions(-) create mode 100644 indra/llui/llwindowshade.cpp create mode 100644 indra/llui/llwindowshade.h diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index e98201ea63..063e3906c7 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -111,6 +111,7 @@ set(llui_SOURCE_FILES llviewmodel.cpp llview.cpp llviewquery.cpp + llwindowshade.cpp ) set(llui_HEADER_FILES @@ -209,6 +210,7 @@ set(llui_HEADER_FILES llviewmodel.h llview.h llviewquery.h + llwindowshade.h ) set_source_files_properties(${llui_HEADER_FILES} diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 9e8539c716..e43669d893 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -173,6 +173,9 @@ public: ~LLLayoutPanel(); void initFromParams(const Params& p); + void setMinDim(S32 value) { mMinDim = value; } + void setMaxDim(S32 value) { mMaxDim = value; } + protected: LLLayoutPanel(const Params& p) ; diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 3ac3bf8c41..d81f425cce 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -823,7 +823,7 @@ LLUICtrl* LLUICtrl::findRootMostFocusRoot() { LLUICtrl* focus_root = NULL; LLUICtrl* next_view = this; - while(next_view) + while(next_view && next_view->hasTabStop()) { if (next_view->isFocusRoot()) { diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 33d345beff..cd2f215c2d 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -412,14 +412,9 @@ public: LLControlVariable *findControl(const std::string& name); - // Moved setValue(), getValue(), setControlValue(), setControlName(), - // controlListener() to LLUICtrl because an LLView is NOT assumed to - // contain a value. If that's what you want, use LLUICtrl instead. -// virtual bool handleEvent(LLPointer event, const LLSD& userdata); - const child_list_t* getChildList() const { return &mChildList; } - const child_list_const_iter_t beginChild() { return mChildList.begin(); } - const child_list_const_iter_t endChild() { return mChildList.end(); } + child_list_const_iter_t beginChild() const { return mChildList.begin(); } + child_list_const_iter_t endChild() const { return mChildList.end(); } // LLMouseHandler functions // Default behavior is to pass events to children diff --git a/indra/llui/llwindowshade.cpp b/indra/llui/llwindowshade.cpp new file mode 100644 index 0000000000..77e94385d4 --- /dev/null +++ b/indra/llui/llwindowshade.cpp @@ -0,0 +1,328 @@ +/** + * @file LLWindowShade.cpp + * @brief Notification dialog that slides down and optionally disabled a piece of UI + * + * $LicenseInfo:firstyear=2006&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 "linden_common.h" +#include "llwindowshade.h" + +#include "lllayoutstack.h" +#include "lltextbox.h" +#include "lliconctrl.h" +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "lllineeditor.h" + +const S32 MIN_NOTIFICATION_AREA_HEIGHT = 30; +const S32 MAX_NOTIFICATION_AREA_HEIGHT = 100; + +LLWindowShade::Params::Params() +: bg_image("bg_image"), + modal("modal", false), + text_color("text_color"), + can_close("can_close", true) +{ + mouse_opaque = false; +} + +LLWindowShade::LLWindowShade(const LLWindowShade::Params& params) +: LLUICtrl(params), + mNotification(params.notification), + mModal(params.modal), + mFormHeight(0), + mTextColor(params.text_color) +{ + setFocusRoot(true); +} + +void LLWindowShade::initFromParams(const LLWindowShade::Params& params) +{ + LLUICtrl::initFromParams(params); + + LLLayoutStack::Params layout_p; + layout_p.name = "notification_stack"; + layout_p.rect = params.rect; + layout_p.follows.flags = FOLLOWS_ALL; + layout_p.mouse_opaque = false; + layout_p.orientation = LLLayoutStack::VERTICAL; + layout_p.border_size = 0; + + LLLayoutStack* stackp = LLUICtrlFactory::create(layout_p); + addChild(stackp); + + LLLayoutPanel::Params panel_p; + panel_p.rect = LLRect(0, 30, 800, 0); + panel_p.name = "notification_area"; + panel_p.visible = false; + panel_p.user_resize = false; + panel_p.background_visible = true; + panel_p.bg_alpha_image = params.bg_image; + panel_p.auto_resize = false; + LLLayoutPanel* notification_panel = LLUICtrlFactory::create(panel_p); + stackp->addChild(notification_panel); + + panel_p = LLUICtrlFactory::getDefaultParams(); + panel_p.auto_resize = true; + panel_p.user_resize = false; + panel_p.rect = params.rect; + panel_p.name = "background_area"; + panel_p.mouse_opaque = false; + panel_p.background_visible = false; + panel_p.bg_alpha_color = LLColor4(0.f, 0.f, 0.f, 0.2f); + LLLayoutPanel* dummy_panel = LLUICtrlFactory::create(panel_p); + stackp->addChild(dummy_panel); + + layout_p = LLUICtrlFactory::getDefaultParams(); + layout_p.rect = LLRect(0, 30, 800, 0); + layout_p.follows.flags = FOLLOWS_ALL; + layout_p.orientation = LLLayoutStack::HORIZONTAL; + stackp = LLUICtrlFactory::create(layout_p); + notification_panel->addChild(stackp); + + panel_p = LLUICtrlFactory::getDefaultParams(); + panel_p.rect.height = 30; + LLLayoutPanel* panel = LLUICtrlFactory::create(panel_p); + stackp->addChild(panel); + + LLIconCtrl::Params icon_p; + icon_p.name = "notification_icon"; + icon_p.rect = LLRect(5, 23, 21, 8); + panel->addChild(LLUICtrlFactory::create(icon_p)); + + LLTextBox::Params text_p; + text_p.rect = LLRect(31, 20, panel->getRect().getWidth() - 5, 0); + text_p.follows.flags = FOLLOWS_ALL; + text_p.text_color = mTextColor; + text_p.font = LLFontGL::getFontSansSerifSmall(); + text_p.font.style = "BOLD"; + text_p.name = "notification_text"; + text_p.use_ellipses = true; + text_p.wrap = true; + panel->addChild(LLUICtrlFactory::create(text_p)); + + panel_p = LLUICtrlFactory::getDefaultParams(); + panel_p.auto_resize = false; + panel_p.user_resize = false; + panel_p.name="form_elements"; + panel_p.rect = LLRect(0, 30, 130, 0); + LLLayoutPanel* form_elements_panel = LLUICtrlFactory::create(panel_p); + stackp->addChild(form_elements_panel); + + if (params.can_close) + { + panel_p = LLUICtrlFactory::getDefaultParams(); + panel_p.auto_resize = false; + panel_p.user_resize = false; + panel_p.rect = LLRect(0, 30, 25, 0); + LLLayoutPanel* close_panel = LLUICtrlFactory::create(panel_p); + stackp->addChild(close_panel); + + LLButton::Params button_p; + button_p.name = "close_notification"; + button_p.rect = LLRect(5, 23, 21, 7); + button_p.image_color.control="DkGray_66"; + button_p.image_unselected.name="Icon_Close_Foreground"; + button_p.image_selected.name="Icon_Close_Press"; + button_p.click_callback.function = boost::bind(&LLWindowShade::onCloseNotification, this); + + close_panel->addChild(LLUICtrlFactory::create(button_p)); + } + + LLSD payload = mNotification->getPayload(); + + LLNotificationFormPtr formp = mNotification->getForm(); + LLLayoutPanel& notification_area = getChildRef("notification_area"); + notification_area.getChild("notification_icon")->setValue(mNotification->getIcon()); + notification_area.getChild("notification_text")->setValue(mNotification->getMessage()); + notification_area.getChild("notification_text")->setToolTip(mNotification->getMessage()); + + LLNotificationForm::EIgnoreType ignore_type = formp->getIgnoreType(); + LLLayoutPanel& form_elements = notification_area.getChildRef("form_elements"); + form_elements.deleteAllChildren(); + + const S32 FORM_PADDING_HORIZONTAL = 10; + const S32 FORM_PADDING_VERTICAL = 3; + const S32 WIDGET_HEIGHT = 24; + const S32 LINE_EDITOR_WIDTH = 120; + S32 cur_x = FORM_PADDING_HORIZONTAL; + S32 cur_y = FORM_PADDING_VERTICAL + WIDGET_HEIGHT; + S32 form_width = cur_x; + + if (ignore_type != LLNotificationForm::IGNORE_NO) + { + LLCheckBoxCtrl::Params checkbox_p; + checkbox_p.name = "ignore_check"; + checkbox_p.rect = LLRect(cur_x, cur_y, cur_x, cur_y - WIDGET_HEIGHT); + checkbox_p.label = formp->getIgnoreMessage(); + checkbox_p.label_text.text_color = LLColor4::black; + checkbox_p.commit_callback.function = boost::bind(&LLWindowShade::onClickIgnore, this, _1); + checkbox_p.initial_value = formp->getIgnored(); + + LLCheckBoxCtrl* check = LLUICtrlFactory::create(checkbox_p); + check->setRect(check->getBoundingRect()); + form_elements.addChild(check); + cur_x = check->getRect().mRight + FORM_PADDING_HORIZONTAL; + form_width = llmax(form_width, cur_x); + } + + for (S32 i = 0; i < formp->getNumElements(); i++) + { + LLSD form_element = formp->getElement(i); + std::string type = form_element["type"].asString(); + if (type == "button") + { + LLButton::Params button_p; + button_p.name = form_element["name"]; + button_p.label = form_element["text"]; + button_p.rect = LLRect(cur_x, cur_y, cur_x, cur_y - WIDGET_HEIGHT); + button_p.click_callback.function = boost::bind(&LLWindowShade::onClickNotificationButton, this, form_element["name"].asString()); + button_p.auto_resize = true; + + LLButton* button = LLUICtrlFactory::create(button_p); + button->autoResize(); + form_elements.addChild(button); + + if (form_element["default"].asBoolean()) + { + form_elements.setDefaultBtn(button); + } + + cur_x = button->getRect().mRight + FORM_PADDING_HORIZONTAL; + form_width = llmax(form_width, cur_x); + } + else if (type == "text" || type == "password") + { + // if not at beginning of line... + if (cur_x != FORM_PADDING_HORIZONTAL) + { + // start new line + cur_x = FORM_PADDING_HORIZONTAL; + cur_y -= WIDGET_HEIGHT + FORM_PADDING_VERTICAL; + } + LLTextBox::Params label_p; + label_p.name = form_element["name"].asString() + "_label"; + label_p.rect = LLRect(cur_x, cur_y, cur_x + LINE_EDITOR_WIDTH, cur_y - WIDGET_HEIGHT); + label_p.initial_value = form_element["text"]; + label_p.text_color = mTextColor; + label_p.font_valign = LLFontGL::VCENTER; + label_p.v_pad = 5; + LLTextBox* textbox = LLUICtrlFactory::create(label_p); + textbox->reshapeToFitText(); + textbox->reshape(textbox->getRect().getWidth(), form_elements.getRect().getHeight() - 2 * FORM_PADDING_VERTICAL); + form_elements.addChild(textbox); + cur_x = textbox->getRect().mRight + FORM_PADDING_HORIZONTAL; + + LLLineEditor::Params line_p; + line_p.name = form_element["name"]; + line_p.keystroke_callback = boost::bind(&LLWindowShade::onEnterNotificationText, this, _1, form_element["name"].asString()); + line_p.is_password = type == "password"; + line_p.rect = LLRect(cur_x, cur_y, cur_x + LINE_EDITOR_WIDTH, cur_y - WIDGET_HEIGHT); + + LLLineEditor* line_editor = LLUICtrlFactory::create(line_p); + form_elements.addChild(line_editor); + form_width = llmax(form_width, cur_x + LINE_EDITOR_WIDTH + FORM_PADDING_HORIZONTAL); + + // reset to start of next line + cur_x = FORM_PADDING_HORIZONTAL; + cur_y -= WIDGET_HEIGHT + FORM_PADDING_VERTICAL; + } + } + + mFormHeight = form_elements.getRect().getHeight() - (cur_y - FORM_PADDING_VERTICAL) + WIDGET_HEIGHT; + form_elements.reshape(form_width, mFormHeight); + form_elements.setMinDim(form_width); + + // move all form elements back onto form surface + S32 delta_y = WIDGET_HEIGHT + FORM_PADDING_VERTICAL - cur_y; + for (child_list_const_iter_t it = form_elements.getChildList()->begin(), end_it = form_elements.getChildList()->end(); + it != end_it; + ++it) + { + (*it)->translate(0, delta_y); + } +} + +void LLWindowShade::show() +{ + getChildRef("notification_area").setVisible(true); + getChildRef("background_area").setBackgroundVisible(mModal); + + setMouseOpaque(mModal); +} + +void LLWindowShade::draw() +{ + LLRect message_rect = getChild("notification_text")->getTextBoundingRect(); + + LLLayoutPanel* notification_area = getChild("notification_area"); + + notification_area->reshape(notification_area->getRect().getWidth(), + llclamp(message_rect.getHeight() + 10, + llmin(mFormHeight, MAX_NOTIFICATION_AREA_HEIGHT), + MAX_NOTIFICATION_AREA_HEIGHT)); + + LLUICtrl::draw(); + if (mNotification && !mNotification->isActive()) + { + hide(); + } +} + +void LLWindowShade::hide() +{ + getChildRef("notification_area").setVisible(false); + getChildRef("background_area").setBackgroundVisible(false); + + setMouseOpaque(false); +} + +void LLWindowShade::onCloseNotification() +{ + LLNotifications::instance().cancel(mNotification); +} + +void LLWindowShade::onClickIgnore(LLUICtrl* ctrl) +{ + bool check = ctrl->getValue().asBoolean(); + if (mNotification && mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN) + { + // question was "show again" so invert value to get "ignore" + check = !check; + } + mNotification->setIgnored(check); +} + +void LLWindowShade::onClickNotificationButton(const std::string& name) +{ + if (!mNotification) return; + + mNotificationResponse[name] = true; + + mNotification->respond(mNotificationResponse); +} + +void LLWindowShade::onEnterNotificationText(LLUICtrl* ctrl, const std::string& name) +{ + mNotificationResponse[name] = ctrl->getValue().asString(); +} diff --git a/indra/llui/llwindowshade.h b/indra/llui/llwindowshade.h new file mode 100644 index 0000000000..0047195929 --- /dev/null +++ b/indra/llui/llwindowshade.h @@ -0,0 +1,69 @@ +/** + * @file llwindowshade.h + * @brief Notification dialog that slides down and optionally disabled a piece of UI + * + * $LicenseInfo:firstyear=2006&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_LLWINDOWSHADE_H +#define LL_LLWINDOWSHADE_H + +#include "lluictrl.h" +#include "llnotifications.h" + +class LLWindowShade : public LLUICtrl +{ +public: + struct Params : public LLInitParam::Block + { + Mandatory notification; + Optional bg_image; + Optional text_color; + Optional modal, + can_close; + + Params(); + }; + + void show(); + /*virtual*/ void draw(); + void hide(); + +private: + friend class LLUICtrlFactory; + + LLWindowShade(const Params& p); + void initFromParams(const Params& params); + + void onCloseNotification(); + void onClickNotificationButton(const std::string& name); + void onEnterNotificationText(LLUICtrl* ctrl, const std::string& name); + void onClickIgnore(LLUICtrl* ctrl); + + LLNotificationPtr mNotification; + LLSD mNotificationResponse; + bool mModal; + S32 mFormHeight; + LLUIColor mTextColor; +}; + +#endif // LL_LLWINDOWSHADE_H diff --git a/indra/newview/llbrowsernotification.cpp b/indra/newview/llbrowsernotification.cpp index 633ef4f1ce..6e77d1e336 100644 --- a/indra/newview/llbrowsernotification.cpp +++ b/indra/newview/llbrowsernotification.cpp @@ -31,6 +31,7 @@ #include "llnotifications.h" #include "llmediactrl.h" #include "llviewermedia.h" +#include "llviewermediafocus.h" using namespace LLNotificationsUI; @@ -39,10 +40,19 @@ bool LLBrowserNotification::processNotification(const LLSD& notify) LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID()); if (!notification) return false; - LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(notification->getPayload()["media_id"].asUUID()); + LLUUID media_id = notification->getPayload()["media_id"].asUUID(); + LLMediaCtrl* media_instance = LLMediaCtrl::getInstance(media_id); if (media_instance) { media_instance->showNotification(notification); } + else if (LLViewerMediaFocus::instance().getControlsMediaID() == media_id) + { + LLViewerMediaImpl* impl = LLViewerMedia::getMediaImplFromTextureID(media_id); + if (impl) + { + impl->showNotification(notification); + } + } return false; } diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index eaa2a60938..6ae95a9039 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -57,264 +57,12 @@ #include "lllineeditor.h" #include "llfloatermediabrowser.h" #include "llfloaterwebcontent.h" +#include "llwindowshade.h" extern BOOL gRestoreGL; static LLDefaultChildRegistry::Register r("web_browser"); -class LLWindowShade : public LLView -{ -public: - struct Params : public LLInitParam::Block - { - Mandatory notification; - Optional bg_image; - - Params() - : bg_image("bg_image") - { - mouse_opaque = false; - } - }; - - void show(); - /*virtual*/ void draw(); - void hide(); - -private: - friend class LLUICtrlFactory; - - LLWindowShade(const Params& p); - void initFromParams(const Params& params); - - void onCloseNotification(); - void onClickNotificationButton(const std::string& name); - void onEnterNotificationText(LLUICtrl* ctrl, const std::string& name); - void onClickIgnore(LLUICtrl* ctrl); - - LLNotificationPtr mNotification; - LLSD mNotificationResponse; -}; - -LLWindowShade::LLWindowShade(const LLWindowShade::Params& params) -: LLView(params), - mNotification(params.notification) -{ -} - -void LLWindowShade::initFromParams(const LLWindowShade::Params& params) -{ - LLView::initFromParams(params); - - LLLayoutStack::Params layout_p; - layout_p.name = "notification_stack"; - layout_p.rect = LLRect(0,getLocalRect().mTop,getLocalRect().mRight, 30); - layout_p.follows.flags = FOLLOWS_ALL; - layout_p.mouse_opaque = false; - layout_p.orientation = LLLayoutStack::VERTICAL; - - LLLayoutStack* stackp = LLUICtrlFactory::create(layout_p); - addChild(stackp); - - LLLayoutPanel::Params panel_p; - panel_p.rect = LLRect(0, 30, 800, 0); - panel_p.min_height = 30; - panel_p.name = "notification_area"; - panel_p.visible = false; - panel_p.user_resize = false; - panel_p.background_visible = true; - panel_p.bg_alpha_image = params.bg_image; - panel_p.auto_resize = false; - LLLayoutPanel* notification_panel = LLUICtrlFactory::create(panel_p); - stackp->addChild(notification_panel); - - panel_p = LLUICtrlFactory::getDefaultParams(); - panel_p.auto_resize = true; - panel_p.mouse_opaque = false; - LLLayoutPanel* dummy_panel = LLUICtrlFactory::create(panel_p); - stackp->addChild(dummy_panel); - - layout_p = LLUICtrlFactory::getDefaultParams(); - layout_p.rect = LLRect(0, 30, 800, 0); - layout_p.follows.flags = FOLLOWS_ALL; - layout_p.orientation = LLLayoutStack::HORIZONTAL; - stackp = LLUICtrlFactory::create(layout_p); - notification_panel->addChild(stackp); - - panel_p = LLUICtrlFactory::getDefaultParams(); - panel_p.rect.height = 30; - LLLayoutPanel* panel = LLUICtrlFactory::create(panel_p); - stackp->addChild(panel); - - LLIconCtrl::Params icon_p; - icon_p.name = "notification_icon"; - icon_p.rect = LLRect(5, 23, 21, 8); - panel->addChild(LLUICtrlFactory::create(icon_p)); - - LLTextBox::Params text_p; - text_p.rect = LLRect(31, 20, 430, 0); - text_p.text_color = LLColor4::black; - text_p.font = LLFontGL::getFontSansSerif(); - text_p.font.style = "BOLD"; - text_p.name = "notification_text"; - text_p.use_ellipses = true; - panel->addChild(LLUICtrlFactory::create(text_p)); - - panel_p = LLUICtrlFactory::getDefaultParams(); - panel_p.auto_resize = false; - panel_p.user_resize = false; - panel_p.name="form_elements"; - panel_p.rect = LLRect(0, 30, 130, 0); - LLLayoutPanel* form_elements_panel = LLUICtrlFactory::create(panel_p); - stackp->addChild(form_elements_panel); - - panel_p = LLUICtrlFactory::getDefaultParams(); - panel_p.auto_resize = false; - panel_p.user_resize = false; - panel_p.rect = LLRect(0, 30, 25, 0); - LLLayoutPanel* close_panel = LLUICtrlFactory::create(panel_p); - stackp->addChild(close_panel); - - LLButton::Params button_p; - button_p.name = "close_notification"; - button_p.rect = LLRect(5, 23, 21, 7); - button_p.image_color=LLUIColorTable::instance().getColor("DkGray_66"); - button_p.image_unselected.name="Icon_Close_Foreground"; - button_p.image_selected.name="Icon_Close_Press"; - button_p.click_callback.function = boost::bind(&LLWindowShade::onCloseNotification, this); - - close_panel->addChild(LLUICtrlFactory::create(button_p)); - - LLSD payload = mNotification->getPayload(); - - LLNotificationFormPtr formp = mNotification->getForm(); - LLLayoutPanel& notification_area = getChildRef("notification_area"); - notification_area.getChild("notification_icon")->setValue(mNotification->getIcon()); - notification_area.getChild("notification_text")->setValue(mNotification->getMessage()); - notification_area.getChild("notification_text")->setToolTip(mNotification->getMessage()); - LLNotificationForm::EIgnoreType ignore_type = formp->getIgnoreType(); - LLLayoutPanel& form_elements = notification_area.getChildRef("form_elements"); - form_elements.deleteAllChildren(); - - const S32 FORM_PADDING_HORIZONTAL = 10; - const S32 FORM_PADDING_VERTICAL = 3; - S32 cur_x = FORM_PADDING_HORIZONTAL; - - if (ignore_type != LLNotificationForm::IGNORE_NO) - { - LLCheckBoxCtrl::Params checkbox_p; - checkbox_p.name = "ignore_check"; - checkbox_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x, FORM_PADDING_VERTICAL); - checkbox_p.label = formp->getIgnoreMessage(); - checkbox_p.label_text.text_color = LLColor4::black; - checkbox_p.commit_callback.function = boost::bind(&LLWindowShade::onClickIgnore, this, _1); - checkbox_p.initial_value = formp->getIgnored(); - - LLCheckBoxCtrl* check = LLUICtrlFactory::create(checkbox_p); - check->setRect(check->getBoundingRect()); - form_elements.addChild(check); - cur_x = check->getRect().mRight + FORM_PADDING_HORIZONTAL; - } - - for (S32 i = 0; i < formp->getNumElements(); i++) - { - LLSD form_element = formp->getElement(i); - std::string type = form_element["type"].asString(); - if (type == "button") - { - LLButton::Params button_p; - button_p.name = form_element["name"]; - button_p.label = form_element["text"]; - button_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x, FORM_PADDING_VERTICAL); - button_p.click_callback.function = boost::bind(&LLWindowShade::onClickNotificationButton, this, form_element["name"].asString()); - button_p.auto_resize = true; - - LLButton* button = LLUICtrlFactory::create(button_p); - button->autoResize(); - form_elements.addChild(button); - - cur_x = button->getRect().mRight + FORM_PADDING_HORIZONTAL; - } - else if (type == "text" || type == "password") - { - LLTextBox::Params label_p; - label_p.name = form_element["name"].asString() + "_label"; - label_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x + 120, FORM_PADDING_VERTICAL); - label_p.initial_value = form_element["text"]; - label_p.text_color = LLColor4::black; - LLTextBox* textbox = LLUICtrlFactory::create(label_p); - textbox->reshapeToFitText(); - form_elements.addChild(textbox); - cur_x = textbox->getRect().mRight + FORM_PADDING_HORIZONTAL; - - LLLineEditor::Params line_p; - line_p.name = form_element["name"]; - line_p.commit_callback.function = boost::bind(&LLWindowShade::onEnterNotificationText, this, _1, form_element["name"].asString()); - line_p.commit_on_focus_lost = true; - line_p.is_password = type == "password"; - line_p.rect = LLRect(cur_x, form_elements.getRect().getHeight() - FORM_PADDING_VERTICAL, cur_x + 120, FORM_PADDING_VERTICAL); - - LLLineEditor* line_editor = LLUICtrlFactory::create(line_p); - form_elements.addChild(line_editor); - cur_x = line_editor->getRect().mRight + FORM_PADDING_HORIZONTAL; - } - } - - form_elements.reshape(cur_x, form_elements.getRect().getHeight()); -} - -void LLWindowShade::show() -{ - LLLayoutPanel& panel = getChildRef("notification_area"); - panel.setVisible(true); -} - -void LLWindowShade::draw() -{ - LLView::draw(); - if (mNotification && !mNotification->isActive()) - { - hide(); - } -} - -void LLWindowShade::hide() -{ - LLLayoutPanel& panel = getChildRef("notification_area"); - panel.setVisible(false); -} - -void LLWindowShade::onCloseNotification() -{ - LLNotifications::instance().cancel(mNotification); -} - -void LLWindowShade::onClickIgnore(LLUICtrl* ctrl) -{ - bool check = ctrl->getValue().asBoolean(); - if (mNotification && mNotification->getForm()->getIgnoreType() == LLNotificationForm::IGNORE_SHOW_AGAIN) - { - // question was "show again" so invert value to get "ignore" - check = !check; - } - mNotification->setIgnored(check); -} - -void LLWindowShade::onClickNotificationButton(const std::string& name) -{ - if (!mNotification) return; - - mNotificationResponse[name] = true; - - mNotification->respond(mNotificationResponse); -} - -void LLWindowShade::onEnterNotificationText(LLUICtrl* ctrl, const std::string& name) -{ - mNotificationResponse[name] = ctrl->getValue().asString(); -} - - LLMediaCtrl::Params::Params() : start_url("start_url"), border_visible("border_visible", true), @@ -1305,7 +1053,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LLNotification::Params auth_request_params; auth_request_params.name = "AuthRequest"; auth_request_params.payload = LLSD().with("media_id", mMediaTextureID); - auth_request_params.functor.function = boost::bind(&LLMediaCtrl::onAuthSubmit, this, _1, _2); + auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2, mMediaSource->getMediaPlugin()); LLNotifications::instance().add(auth_request_params); }; break; @@ -1351,31 +1099,27 @@ void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) } } -void LLMediaCtrl::onAuthSubmit(const LLSD& notification, const LLSD& response) -{ - if (response["ok"]) - { - mMediaSource->getMediaPlugin()->sendAuthResponse(true, response["username"], response["password"]); - } - else - { - mMediaSource->getMediaPlugin()->sendAuthResponse(false, "", ""); - } -} - - void LLMediaCtrl::showNotification(LLNotificationPtr notify) { delete mWindowShade; LLWindowShade::Params params; + params.name = "notification_shade"; params.rect = getLocalRect(); params.follows.flags = FOLLOWS_ALL; params.notification = notify; + params.modal = true; //HACK: don't hardcode this - if (notify->getName() == "PopupAttempt") + if (notify->getIcon() == "Popup_Caution") { params.bg_image.name = "Yellow_Gradient"; + params.text_color = LLColor4::black; + } + else + { + //HACK: make this a property of the notification itself, "cancellable" + params.can_close = false; + params.text_color.control = "LabelTextColor"; } mWindowShade = LLUICtrlFactory::create(params); diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 0c369840bf..48e4c48376 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -167,7 +167,6 @@ public: private: void onVisibilityChange ( const LLSD& new_visibility ); void onPopup(const LLSD& notification, const LLSD& response); - void onAuthSubmit(const LLSD& notification, const LLSD& response); const S32 mTextureDepthBytes; LLUUID mMediaTextureID; diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index b04971f980..87465ad2be 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -59,6 +59,7 @@ #include "llvovolume.h" #include "llweb.h" #include "llwindow.h" +#include "llwindowshade.h" #include "llfloatertools.h" // to enable hide if build tools are up // Functions pulled from pipeline.cpp @@ -90,7 +91,8 @@ LLPanelPrimMediaControls::LLPanelPrimMediaControls() : mTargetObjectNormal(LLVector3::zero), mZoomObjectID(LLUUID::null), mZoomObjectFace(0), - mVolumeSliderVisible(0) + mVolumeSliderVisible(0), + mWindowShade(NULL) { mCommitCallbackRegistrar.add("MediaCtrl.Close", boost::bind(&LLPanelPrimMediaControls::onClickClose, this)); mCommitCallbackRegistrar.add("MediaCtrl.Back", boost::bind(&LLPanelPrimMediaControls::onClickBack, this)); @@ -205,6 +207,9 @@ BOOL LLPanelPrimMediaControls::postBuild() mMediaAddress->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this )); + LLWindowShade::Params window_shade_params; + window_shade_params.name = "window_shade"; + mCurrentZoom = ZOOM_NONE; // clicks on buttons do not remove keyboard focus from media setIsChrome(TRUE); @@ -698,6 +703,24 @@ void LLPanelPrimMediaControls::updateShape() /*virtual*/ void LLPanelPrimMediaControls::draw() { + LLViewerMediaImpl* impl = getTargetMediaImpl(); + if (impl) + { + LLNotificationPtr notification = impl->getCurrentNotification(); + if (notification != mActiveNotification) + { + mActiveNotification = notification; + if (notification) + { + showNotification(notification); + } + else + { + hideNotification(); + } + } + } + F32 alpha = getDrawContext().mAlpha; if(mFadeTimer.getStarted()) { @@ -1295,3 +1318,38 @@ bool LLPanelPrimMediaControls::shouldVolumeSliderBeVisible() { return mVolumeSliderVisible > 0; } + +void LLPanelPrimMediaControls::showNotification(LLNotificationPtr notify) +{ + delete mWindowShade; + LLWindowShade::Params params; + params.rect = mMediaRegion->getLocalRect(); + params.follows.flags = FOLLOWS_ALL; + params.notification = notify; + + //HACK: don't hardcode this + if (notify->getIcon() == "Popup_Caution") + { + params.bg_image.name = "Yellow_Gradient"; + params.text_color = LLColor4::black; + } + else + { + //HACK: make this a property of the notification itself, "cancellable" + params.can_close = false; + params.text_color.control = "LabelTextColor"; + } + + mWindowShade = LLUICtrlFactory::create(params); + + mMediaRegion->addChild(mWindowShade); + mWindowShade->show(); +} + +void LLPanelPrimMediaControls::hideNotification() +{ + if (mWindowShade) + { + mWindowShade->hide(); + } +} diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 3ec24f0e24..0b9664359c 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -29,6 +29,7 @@ #include "llpanel.h" #include "llviewermedia.h" +#include "llnotificationptr.h" class LLButton; class LLCoordWindow; @@ -37,6 +38,7 @@ class LLLayoutStack; class LLProgressBar; class LLSliderCtrl; class LLViewerMediaImpl; +class LLWindowShade; class LLPanelPrimMediaControls : public LLPanel { @@ -54,6 +56,9 @@ public: void updateShape(); bool isMouseOver(); + void showNotification(LLNotificationPtr notify); + void hideNotification(); + enum EZoomLevel { ZOOM_NONE = 0, @@ -162,6 +167,7 @@ private: LLUICtrl *mRightBookend; LLUIImage* mBackgroundImage; LLUIImage* mVolumeSliderBackgroundImage; + LLWindowShade* mWindowShade; F32 mSkipStep; S32 mMinWidth; S32 mMinHeight; @@ -204,6 +210,8 @@ private: S32 mZoomObjectFace; S32 mVolumeSliderVisible; + + LLNotificationPtr mActiveNotification; }; #endif // LL_PANELPRIMMEDIACONTROLS_H diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index be4e23728a..4a50b1717e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -52,6 +52,7 @@ #include "llviewerregion.h" #include "llwebsharing.h" // For LLWebSharing::setOpenIDCookie(), *TODO: find a better way to do this! #include "llfilepicker.h" +#include "llnotifications.h" #include "llevent.h" // LLSimpleListener #include "llnotificationsutil.h" @@ -1044,6 +1045,18 @@ bool LLViewerMedia::isParcelAudioPlaying() return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying()); } +void LLViewerMedia::onAuthSubmit(const LLSD& notification, const LLSD& response, LLPluginClassMedia* media) +{ + if (response["ok"]) + { + media->sendAuthResponse(true, response["username"], response["password"]); + } + else + { + media->sendAuthResponse(false, "", ""); + } +} + ///////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerMedia::clearAllCookies() @@ -1912,6 +1925,18 @@ void LLViewerMediaImpl::setSize(int width, int height) } } +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::showNotification(LLNotificationPtr notify) +{ + mNotification = notify; +} + +////////////////////////////////////////////////////////////////////////////////////////// +void LLViewerMediaImpl::hideNotification() +{ + mNotification.reset(); +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::play() { @@ -2976,6 +3001,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_BEGIN: { LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_BEGIN, uri is: " << plugin->getNavigateURI() << LL_ENDL; + hideNotification(); if(getNavState() == MEDIANAVSTATE_SERVER_SENT) { @@ -3067,13 +3093,17 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla } break; + case LLViewerMediaObserver::MEDIA_EVENT_AUTH_REQUEST: { - llinfos << "MEDIA_EVENT_AUTH_REQUEST, url " << plugin->getAuthURL() << ", realm " << plugin->getAuthRealm() << LL_ENDL; - //plugin->sendAuthResponse(false, "", ""); - } + LLNotification::Params auth_request_params; + auth_request_params.name = "AuthRequest"; + auth_request_params.payload = LLSD().with("media_id", mTextureId); + auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2, plugin); + LLNotifications::instance().add(auth_request_params); + }; break; - + case LLViewerMediaObserver::MEDIA_EVENT_CLOSE_REQUEST: { std::string uuid = plugin->getClickUUID(); @@ -3591,6 +3621,11 @@ bool LLViewerMediaImpl::isInAgentParcel() const return result; } +LLNotificationPtr LLViewerMediaImpl::getCurrentNotification() const +{ + return mNotification; +} + ////////////////////////////////////////////////////////////////////////////////////////// // // static diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 6f8d12e676..83fe790839 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -37,6 +37,7 @@ #include "llpluginclassmedia.h" #include "v4color.h" +#include "llnotificationptr.h" #include "llurl.h" @@ -130,6 +131,8 @@ public: static bool isParcelMediaPlaying(); static bool isParcelAudioPlaying(); + static void onAuthSubmit(const LLSD& notification, const LLSD& response, LLPluginClassMedia* media); + // Clear all cookies for all plugins static void clearAllCookies(); @@ -199,6 +202,9 @@ public: LLPluginClassMedia* getMediaPlugin() { return mMediaSource; } void setSize(int width, int height); + void showNotification(LLNotificationPtr notify); + void hideNotification(); + void play(); void stop(); void pause(); @@ -391,6 +397,9 @@ public: // Is this media in the agent's parcel? bool isInAgentParcel() const; + // get currently active notification associated with this media instance + LLNotificationPtr getCurrentNotification() const; + private: bool isAutoPlayable() const; bool shouldShowBasedOnClass() const; @@ -448,7 +457,8 @@ private: bool mNavigateSuspendedDeferred; bool mTrustedBrowser; std::string mTarget; - + LLNotificationPtr mNotification; + private: BOOL mIsUpdated ; std::list< LLVOVolume* > mObjectList ; diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp index de52aa17d1..72a494201d 100644 --- a/indra/newview/llviewermediafocus.cpp +++ b/indra/newview/llviewermediafocus.cpp @@ -592,4 +592,4 @@ LLUUID LLViewerMediaFocus::getControlsMediaID() } return LLUUID::null; -} +} \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/menu_login.xml b/indra/newview/skins/default/xui/en/menu_login.xml index 271b688be5..0d4a095e14 100644 --- a/indra/newview/skins/default/xui/en/menu_login.xml +++ b/indra/newview/skins/default/xui/en/menu_login.xml @@ -189,7 +189,6 @@ function="Advanced.WebContentTest" parameter="http://www.google.com"/> - Date: Fri, 10 Dec 2010 11:03:34 -0800 Subject: destroy updater state machine if login instance destroyed. --- indra/newview/lllogininstance.cpp | 10 +++++++++- indra/newview/lllogininstance.h | 5 ++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index 1858cbdcd9..8d9d7298f8 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -64,8 +64,15 @@ #include #include +class LLLoginInstance::Disposable { +public: + virtual ~Disposable() {} +}; + namespace { - class MandatoryUpdateMachine { + class MandatoryUpdateMachine: + public LLLoginInstance::Disposable + { public: MandatoryUpdateMachine(LLLoginInstance & loginInstance, LLUpdaterService & updaterService); @@ -754,6 +761,7 @@ void LLLoginInstance::updateApp(bool mandatory, const std::string& auth_msg) { gViewerWindow->setShowProgress(false); MandatoryUpdateMachine * machine = new MandatoryUpdateMachine(*this, *mUpdaterService); + mUpdateStateMachine.reset(machine); machine->start(); return; } diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index cb1f56a971..b872d7d1b1 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -41,6 +41,8 @@ class LLUpdaterService; class LLLoginInstance : public LLSingleton { public: + class Disposable; + LLLoginInstance(); ~LLLoginInstance(); @@ -106,7 +108,8 @@ private: int mLastExecEvent; UpdaterLauncherCallback mUpdaterLauncher; LLEventDispatcher mDispatcher; - LLUpdaterService * mUpdaterService; + LLUpdaterService * mUpdaterService; + boost::scoped_ptr mUpdateStateMachine; }; #endif -- cgit v1.2.3 From 1924f1bbca437eac4ca5d047c489042e65904d2e Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Fri, 10 Dec 2010 11:26:23 -0800 Subject: no bandwidth limit for required downloads. --- indra/viewer_components/updater/llupdatedownloader.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index d67de1c83b..2dd0084fdc 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -275,7 +275,7 @@ void LLUpdateDownloader::Implementation::resume(void) void LLUpdateDownloader::Implementation::setBandwidthLimit(U64 bytesPerSecond) { - if((mBandwidthLimit != bytesPerSecond) && isDownloading()) { + if((mBandwidthLimit != bytesPerSecond) && isDownloading() && !mDownloadData["required"].asBoolean()) { llassert(mCurl != 0); mBandwidthLimit = bytesPerSecond; CURLcode code = curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, &mBandwidthLimit); @@ -411,8 +411,10 @@ void LLUpdateDownloader::Implementation::initializeCurlGet(std::string const & u throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSFUNCTION, &progress_callback)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_PROGRESSDATA, this)); throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_NOPROGRESS, false)); - if(mBandwidthLimit != 0) { + if((mBandwidthLimit != 0) && !mDownloadData["required"].asBoolean()) { throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, mBandwidthLimit)); + } else { + throwOnCurlError(curl_easy_setopt(mCurl, CURLOPT_MAX_RECV_SPEED_LARGE, -1)); } mDownloadPercent = 0; -- cgit v1.2.3 From dbcb6b4fa5a1838f64db4198aeca1894ec0008a8 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Fri, 10 Dec 2010 12:06:43 -0800 Subject: fix crash if posting event during shutdown. --- indra/llcommon/llevents.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 84a6620a77..b8a594b9bc 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -475,7 +475,7 @@ void LLEventPump::stopListening(const std::string& name) *****************************************************************************/ bool LLEventStream::post(const LLSD& event) { - if (! mEnabled) + if (! mEnabled || !mSignal) { return false; } -- cgit v1.2.3 From 5f01d6a6861fdcd4c9c09e60a631ed92d2b15a82 Mon Sep 17 00:00:00 2001 From: callum Date: Fri, 10 Dec 2010 12:42:21 -0800 Subject: SOCIAL-364 FIX Viewer Crash when selecting Browse Linden Homes button from side panel --- indra/newview/llmediactrl.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index eaa2a60938..276ffffec4 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -1333,7 +1333,27 @@ void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) { if (response["open"]) { - std::string floater_name = gFloaterView->getParentFloater(this)->getInstanceName(); + // name of default floater to open + std::string floater_name = "web_content"; + + // look for parent floater name + if ( gFloaterView ) + { + if ( gFloaterView->getParentFloater(this) ) + { + floater_name = gFloaterView->getParentFloater(this)->getInstanceName(); + } + else + { + lldebugs << "No gFloaterView->getParentFloater(this) for onPopuup()" << llendl; + }; + } + else + { + lldebugs << "No gFloaterView for onPopuup()" << llendl; + }; + + // open the same kind of floater as parent if possible if ( floater_name == "media_browser" ) { LLWeb::loadURL(notification["payload"]["url"], notification["payload"]["target"], notification["payload"]["uuid"]); -- cgit v1.2.3 From 4bab98f5cd2a815d10fe494a0a7e51cc237adb4a Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Fri, 10 Dec 2010 16:05:19 -0500 Subject: ESC-228 ESC-227 Corrections for metrics counters and send-on-quit delivery. Wanted to avoid computing metrics for duplicate requests as much as possible, they artificially depress averages but missed an opportunity and was including them in the counts. The non-texture case is solid. Textures are.... confounding still. Do a better job of trying to send one last packet to the grid when quitting. It is succeeding now, at least sometimes. Put a comment in base llassetstorage.cpp pointing to cut-n-paste derivation in llviewerassetstorage.cpp so that changes can be replicated. Hate doing this but current design forces it. --- indra/llmessage/llassetstorage.cpp | 4 ++++ indra/newview/llappviewer.cpp | 4 +++- indra/newview/llviewerassetstorage.cpp | 7 ++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index b26d412e9f..27a368df3d 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -513,6 +513,10 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LL } +// +// *NOTE: Logic here is replicated in LLViewerAssetStorage::_queueDataRequest. +// Changes here may need to be replicated in the viewer's derived class. +// void LLAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType atype, LLGetAssetCallback callback, void *user_data, BOOL duplicate, diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 30005258ed..c667fba86f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3036,6 +3036,9 @@ void LLAppViewer::requestQuit() return; } + // Try to send metrics back to the grid + metricsSend(!gDisconnected); + LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral*)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); effectp->setPositionGlobal(gAgent.getPositionGlobal()); effectp->setColor(LLColor4U(gAgent.getEffectColor())); @@ -3053,7 +3056,6 @@ void LLAppViewer::requestQuit() LLSideTray::getInstance()->notifyChildren(LLSD().with("request","quit")); send_stats(); - metricsSend(!gDisconnected); gLogoutTimer.reset(); mQuitRequested = true; diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index 197cb3468c..36c8b42a52 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -348,7 +348,12 @@ void LLViewerAssetStorage::_queueDataRequest( req->mDownCallback = callback; req->mUserData = user_data; req->mIsPriority = is_priority; - req->mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); + if (!duplicate) + { + // Only collect metrics for non-duplicate requests. Others + // are piggy-backing and will artificially lower averages. + req->mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); + } mPendingDownloads.push_back(req); -- cgit v1.2.3 From a738de7d56cfe5607a2016cf99b3afccd4b062a5 Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Fri, 10 Dec 2010 16:03:00 -0800 Subject: Deleting USE_VIEWER_AUTH code. This stuff is old broken glass sitting around waiting to cut you. Rev. by Brad --- indra/newview/llpanellogin.cpp | 100 ----------------------------------------- 1 file changed, 100 deletions(-) diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index cf567fb208..8a1fe114e9 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -73,7 +73,6 @@ #endif // LL_WINDOWS #include "llsdserialize.h" -#define USE_VIEWER_AUTH 0 const S32 BLACK_BORDER_HEIGHT = 160; const S32 MAX_PASSWORD = 16; @@ -189,10 +188,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, buildFromFile( "panel_login.xml"); -#if USE_VIEWER_AUTH - //leave room for the login menu bar - setRect(LLRect(0, rect.getHeight()-18, rect.getWidth(), 0)); -#endif // Legacy login web page is hidden under the menu bar. // Adjust reg-in-client web browser widget to not be hidden. if (gSavedSettings.getBOOL("RegInClient")) @@ -204,7 +199,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, reshape(rect.getWidth(), rect.getHeight()); } -#if !USE_VIEWER_AUTH getChild("password_edit")->setKeystrokeCallback(onPassKey, this); // change z sort of clickable text to be behind buttons @@ -247,7 +241,6 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect, LLTextBox* need_help_text = getChild("login_help"); need_help_text->setClickedCallback(onClickHelp, NULL); -#endif // get the web browser control LLMediaCtrl* web_browser = getChild("login_html"); @@ -274,15 +267,9 @@ void LLPanelLogin::reshapeBrowser() LLMediaCtrl* web_browser = getChild("login_html"); LLRect rect = gViewerWindow->getWindowRectScaled(); LLRect html_rect; -#if USE_VIEWER_AUTH - html_rect.setCenterAndSize( - rect.getCenterX() - 2, rect.getCenterY(), - rect.getWidth() + 6, rect.getHeight()); -#else html_rect.setCenterAndSize( rect.getCenterX() - 2, rect.getCenterY() + 40, rect.getWidth() + 6, rect.getHeight() - 78 ); -#endif web_browser->setRect( html_rect ); web_browser->reshape( html_rect.getWidth(), html_rect.getHeight(), TRUE ); reshape( rect.getWidth(), rect.getHeight(), 1 ); @@ -305,7 +292,6 @@ void LLPanelLogin::setSiteIsAlive( bool alive ) else // the site is not available (missing page, server down, other badness) { -#if !USE_VIEWER_AUTH if ( web_browser ) { // hide browser control (revealing default one) @@ -314,16 +300,6 @@ void LLPanelLogin::setSiteIsAlive( bool alive ) // mark as unavailable mHtmlAvailable = FALSE; } -#else - - if ( web_browser ) - { - web_browser->navigateToLocalPage( "loading-error" , "index.html" ); - - // mark as available - mHtmlAvailable = TRUE; - } -#endif } } @@ -363,7 +339,6 @@ void LLPanelLogin::draw() if ( mHtmlAvailable ) { -#if !USE_VIEWER_AUTH if (getChild("login_widgets")->getVisible()) { // draw a background box in black @@ -372,7 +347,6 @@ void LLPanelLogin::draw() // just the blue background to the native client UI mLogoImage->draw(0, -264, width + 8, mLogoImage->getHeight()); } -#endif } else { @@ -418,12 +392,6 @@ void LLPanelLogin::setFocus(BOOL b) // static void LLPanelLogin::giveFocus() { -#if USE_VIEWER_AUTH - if (sInstance) - { - sInstance->setFocus(TRUE); - } -#else if( sInstance ) { // Grab focus and move cursor to first blank input field @@ -452,7 +420,6 @@ void LLPanelLogin::giveFocus() edit->selectAll(); } } -#endif } // static @@ -832,73 +799,6 @@ void LLPanelLogin::loadLoginPage() curl_free(curl_grid); gViewerWindow->setMenuBackgroundColor(false, !LLGridManager::getInstance()->isInProductionGrid()); gLoginMenuBarView->setBackgroundColor(gMenuBarView->getBackgroundColor()); - - -#if USE_VIEWER_AUTH - LLURLSimString::sInstance.parse(); - - std::string location; - std::string region; - std::string password; - - if (LLURLSimString::parse()) - { - std::ostringstream oRegionStr; - location = "specify"; - oRegionStr << LLURLSimString::sInstance.mSimName << "/" << LLURLSimString::sInstance.mX << "/" - << LLURLSimString::sInstance.mY << "/" - << LLURLSimString::sInstance.mZ; - region = oRegionStr.str(); - } - else - { - location = gSavedSettings.getString("LoginLocation"); - } - - std::string username; - - if(gSavedSettings.getLLSD("UserLoginInfo").size() == 3) - { - LLSD cmd_line_login = gSavedSettings.getLLSD("UserLoginInfo"); - username = cmd_line_login[0].asString() + " " + cmd_line_login[1]; - password = cmd_line_login[2].asString(); - } - - - char* curl_region = curl_escape(region.c_str(), 0); - - oStr <<"username=" << username << - "&location=" << location << "®ion=" << curl_region; - - curl_free(curl_region); - - if (!password.empty()) - { - oStr << "&password=" << password; - } - else if (!(password = load_password_from_disk()).empty()) - { - oStr << "&password=$1$" << password; - } - if (gAutoLogin) - { - oStr << "&auto_login=TRUE"; - } - if (gSavedSettings.getBOOL("ShowStartLocation")) - { - oStr << "&show_start_location=TRUE"; - } - if (gSavedSettings.getBOOL("RememberPassword")) - { - oStr << "&remember_password=TRUE"; - } -#ifndef LL_RELEASE_FOR_DOWNLOAD - oStr << "&show_grid=TRUE"; -#else - if (gSavedSettings.getBOOL("ForceShowGrid")) - oStr << "&show_grid=TRUE"; -#endif -#endif LLMediaCtrl* web_browser = sInstance->getChild("login_html"); -- cgit v1.2.3 From 8f5f68d1cc904e7774e20677237909940c63168d Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Fri, 10 Dec 2010 16:06:33 -0800 Subject: STORM-524 : Fix update L$ balance when buying currency --- indra/newview/llfloaterbuycurrency.cpp | 9 ++++++--- indra/newview/llfloaterbuycurrencyhtml.cpp | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp index 48b00a7964..e21a8594bc 100644 --- a/indra/newview/llfloaterbuycurrency.cpp +++ b/indra/newview/llfloaterbuycurrency.cpp @@ -261,26 +261,29 @@ void LLFloaterBuyCurrencyUI::updateUI() } getChildView("getting_data")->setVisible( !mManager.canBuy() && !hasError); - - // Update L$ balance - LLStatusBar::sendMoneyBalanceRequest(); } void LLFloaterBuyCurrencyUI::onClickBuy() { mManager.buy(getString("buy_currency")); updateUI(); + // Update L$ balance + LLStatusBar::sendMoneyBalanceRequest(); } void LLFloaterBuyCurrencyUI::onClickCancel() { closeFloater(); + // Update L$ balance + LLStatusBar::sendMoneyBalanceRequest(); } void LLFloaterBuyCurrencyUI::onClickErrorWeb() { LLWeb::loadURLExternal(mManager.errorURI()); closeFloater(); + // Update L$ balance + LLStatusBar::sendMoneyBalanceRequest(); } // static diff --git a/indra/newview/llfloaterbuycurrencyhtml.cpp b/indra/newview/llfloaterbuycurrencyhtml.cpp index e8050c4480..013cf74c7b 100644 --- a/indra/newview/llfloaterbuycurrencyhtml.cpp +++ b/indra/newview/llfloaterbuycurrencyhtml.cpp @@ -82,7 +82,7 @@ void LLFloaterBuyCurrencyHTML::navigateToFinalURL() LLStringUtil::format( buy_currency_url, replace ); // write final URL to debug console - llinfos << "Buy currency HTML prased URL is " << buy_currency_url << llendl; + llinfos << "Buy currency HTML parsed URL is " << buy_currency_url << llendl; // kick off the navigation mBrowser->navigateTo( buy_currency_url, "text/html" ); -- cgit v1.2.3 From 56a39aa914fe32c1986202dc39a3ad4604943b39 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Fri, 10 Dec 2010 16:15:18 -0800 Subject: fix possible crash on shutdown in event queue flush. --- indra/llcommon/llevents.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index b8a594b9bc..723cbd68c7 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -515,6 +515,8 @@ bool LLEventQueue::post(const LLSD& event) void LLEventQueue::flush() { + if(!mEnabled || !mSignal) return; + // Consider the case when a given listener on this LLEventQueue posts yet // another event on the same queue. If we loop over mEventQueue directly, // we'll end up processing all those events during the same flush() call -- cgit v1.2.3 From 6c21e9262e357f8c85f4fc5a2d7948836f63f8ae Mon Sep 17 00:00:00 2001 From: "Mark Palange (Mani)" Date: Fri, 10 Dec 2010 16:19:44 -0800 Subject: CHOP-245 removed crufty secondlife.com/app/login url and the dubious code that used it. Rev by Brad --- indra/newview/llpanellogin.cpp | 4 +++- indra/newview/skins/default/xui/en/panel_login.xml | 6 +----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 8a1fe114e9..302e4fa19d 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -425,11 +425,13 @@ void LLPanelLogin::giveFocus() // static void LLPanelLogin::showLoginWidgets() { + // *NOTE: Mani - This may or may not be obselete code. + // It seems to be part of the defunct? reg-in-client project. sInstance->getChildView("login_widgets")->setVisible( true); LLMediaCtrl* web_browser = sInstance->getChild("login_html"); sInstance->reshapeBrowser(); // *TODO: Append all the usual login parameters, like first_login=Y etc. - std::string splash_screen_url = sInstance->getString("real_url"); + std::string splash_screen_url = LLGridManager::getInstance()->getLoginPage(); web_browser->navigateTo( splash_screen_url, "text/html" ); LLUICtrl* username_edit = sInstance->getChild("username_edit"); username_edit->setFocus(TRUE); diff --git a/indra/newview/skins/default/xui/en/panel_login.xml b/indra/newview/skins/default/xui/en/panel_login.xml index 89feba7c3c..00ab17d4a2 100644 --- a/indra/newview/skins/default/xui/en/panel_login.xml +++ b/indra/newview/skins/default/xui/en/panel_login.xml @@ -11,11 +11,7 @@ top="600" name="create_account_url"> http://join.secondlife.com/ - - http://secondlife.com/app/login/ - - + http://secondlife.eniac15.lindenlab.com/reg-in-client/ Date: Fri, 10 Dec 2010 17:41:05 -0800 Subject: Decided to refactor a bit. Was using LLSD as an internal data representation transferring ownership, doing data aggregation in a very pedantic way. That's just adding unneeded cost and complication. Used the same objects to transport data as are collecting it and everything got simpler, faster, easier to read with fewer gotchas. Bit myself *again* doing the min/max/mean merges but the unittests where there to pick me up again. Added a per-region FPS metric while I was at it. This is much asked for and there was a convenient place to sample the value. --- indra/newview/llappviewer.cpp | 31 +- indra/newview/llsimplestat.h | 18 + indra/newview/lltexturefetch.cpp | 98 ++-- indra/newview/lltexturefetch.h | 7 +- indra/newview/llviewerassetstats.cpp | 286 ++++-------- indra/newview/llviewerassetstats.h | 70 ++- indra/newview/tests/llsimplestat_test.cpp | 158 +++++++ indra/newview/tests/llviewerassetstats_test.cpp | 595 ++++++++++++++---------- 8 files changed, 740 insertions(+), 523 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c667fba86f..3640d01642 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3804,6 +3804,11 @@ void LLAppViewer::idle() llinfos << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << llendl; gObjectList.mNumUnknownUpdates = 0; } + + // ViewerMetrics FPS piggy-backing on the debug timer. + // The 5-second interval is nice for this purpose. If the object debug + // bit moves or is disabled, please give this a suitable home. + LLViewerAssetStatsFF::record_fps_main(frame_rate_clamped); } } @@ -4805,23 +4810,17 @@ void LLAppViewer::metricsSend(bool enable_reporting) { std::string caps_url = regionp->getCapability("ViewerMetrics"); - // *NOTE: Pay attention here. LLSD's are not safe for thread sharing - // and their ownership is difficult to transfer across threads. We do - // it here by having only one reference (the new'd pointer) to the LLSD - // or any subtree of it. This pointer is then transfered to the other - // thread using correct thread logic to do all data ordering. - LLSD * envelope = new LLSD(LLSD::emptyMap()); - { - (*envelope) = gViewerAssetStatsMain->asLLSD(); - (*envelope)["session_id"] = gAgentSessionID; - (*envelope)["agent_id"] = gAgentID; - } - + // Make a copy of the main stats to send into another thread. + // Receiving thread takes ownership. + LLViewerAssetStats * main_stats(new LLViewerAssetStats(*gViewerAssetStatsMain)); + // Send a report request into 'thread1' to get the rest of the data - // and have it sent to the stats collector. LLSD ownership transfers - // with this call. - LLAppViewer::sTextureFetch->commandSendMetrics(caps_url, envelope); - envelope = 0; // transfer noted + // and provide some additional parameters while here. + LLAppViewer::sTextureFetch->commandSendMetrics(caps_url, + gAgentSessionID, + gAgentID, + main_stats); + main_stats = 0; // Ownership transferred } else { diff --git a/indra/newview/llsimplestat.h b/indra/newview/llsimplestat.h index f8f4be0390..a90e503adb 100644 --- a/indra/newview/llsimplestat.h +++ b/indra/newview/llsimplestat.h @@ -62,6 +62,9 @@ public: inline void reset() { mCount = 0; } + inline void merge(const LLSimpleStatCounter & src) + { mCount += src.mCount; } + inline U32 operator++() { return ++mCount; } inline U32 getCount() const { return mCount; } @@ -125,6 +128,21 @@ public: ++mCount; } + void merge(const LLSimpleStatMMM & src) + { + if (! mCount) + { + *this = src; + } + else if (src.mCount) + { + mMin = llmin(mMin, src.mMin); + mMax = llmax(mMax, src.mMax); + mCount += src.mCount; + mTotal += src.mTotal; + } + } + inline U32 getCount() const { return mCount; } inline Value getMin() const { return mMin; } inline Value getMax() const { return mMax; } diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 73d78c9334..e1f9d7bdcc 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -442,18 +442,18 @@ namespace * | | TE | . +-------+ * | +--+--+ . | Thd1 | * | | . | | - * | (llsd) +-----+ . | Stats | + * | +-----+ . | Stats | * `--------->| RSC | . | | * +--+--+ . | Coll. | * | . +-------+ * +--+--+ . | * | SME |---. . | * +-----+ \ . | - * . \ (llsd) +-----+ | + * . \ (clone) +-----+ | * . `-------->| SM | | * . +--+--+ | * . | | - * . +-----+ (llsd) | + * . +-----+ | * . | RSC |<--------' * . +-----+ * . | @@ -472,11 +472,12 @@ namespace * SR - Set Region. New region UUID is sent to the thread-local * collector. * SME - Send Metrics Enqueued. Enqueue a 'Send Metrics' command - * including an ownership transfer of an LLSD. + * including an ownership transfer of a cloned LLViewerAssetStats. * TFReqSendMetrics carries the data. * SM - Send Metrics. Global metrics reporting operation. Takes - * the remote LLSD from the command, merges it with and LLSD - * from the local collector and sends it to the grid. + * the cloned stats from the command, merges it with the + * thread's local stats, converts to LLSD and sends it on + * to the grid. * AM - Agent Moved. Agent has completed some sort of move to a * new region. * TE - Timer Expired. Metrics timer has expired (on the order @@ -485,7 +486,8 @@ namespace * MSC - Modify Stats Collector. State change in the thread-local * collector. Typically a region change which affects the * global pointers used to find the 'current stats'. - * RSC - Read Stats Collector. Extract collector data in LLSD form. + * RSC - Read Stats Collector. Extract collector data cloning it + * (i.e. deep copy) when necessary. * */ class TFRequest // : public LLQueuedThread::QueuedRequest @@ -539,11 +541,12 @@ public: * * This is the big operation. The main thread gathers metrics * for a period of minutes into LLViewerAssetStats and other - * objects then builds an LLSD to represent the data. It uses - * this command to transfer the LLSD, content *and* ownership, - * to the TextureFetch thread which adds its own metrics and - * kicks of an HTTP POST of the resulting data to the currently - * active metrics collector. + * objects then makes a snapshot of the data by cloning the + * collector. This command transfers the clone, along with a few + * additional arguments (UUIDs), handing ownership to the + * TextureFetch thread. It then merges its own data into the + * cloned copy, converts to LLSD and kicks off an HTTP POST of + * the resulting data to the currently active metrics collector. * * Corresponds to LLTextureFetch::commandSendMetrics() */ @@ -558,16 +561,24 @@ public: * to receive the data. Does not have to * be associated with a particular region. * - * @param report_main Pointer to LLSD containing main - * thread metrics. Ownership transfers - * to the new thread using very carefully - * constructed code. + * @param session_id UUID of the agent's session. + * + * @param agent_id UUID of the agent. (Being pure here...) + * + * @param main_stats Pointer to a clone of the main thread's + * LLViewerAssetStats data. Thread1 takes + * ownership of the copy and disposes of it + * when done. */ TFReqSendMetrics(const std::string & caps_url, - LLSD * report_main) + const LLUUID & session_id, + const LLUUID & agent_id, + LLViewerAssetStats * main_stats) : TFRequest(), mCapsURL(caps_url), - mReportMain(report_main) + mSessionID(session_id), + mAgentID(agent_id), + mMainStats(main_stats) {} TFReqSendMetrics & operator=(const TFReqSendMetrics &); // Not defined @@ -577,7 +588,9 @@ public: public: const std::string mCapsURL; - LLSD * mReportMain; + const LLUUID mSessionID; + const LLUUID mAgentID; + LLViewerAssetStats * mMainStats; }; /* @@ -2727,9 +2740,11 @@ void LLTextureFetch::commandSetRegion(U64 region_handle) } void LLTextureFetch::commandSendMetrics(const std::string & caps_url, - LLSD * report_main) + const LLUUID & session_id, + const LLUUID & agent_id, + LLViewerAssetStats * main_stats) { - TFReqSendMetrics * req = new TFReqSendMetrics(caps_url, report_main); + TFReqSendMetrics * req = new TFReqSendMetrics(caps_url, session_id, agent_id, main_stats); cmdEnqueue(req); } @@ -2808,14 +2823,14 @@ TFReqSetRegion::doWork(LLTextureFetch *) TFReqSendMetrics::~TFReqSendMetrics() { - delete mReportMain; - mReportMain = 0; + delete mMainStats; + mMainStats = 0; } /** * Implements the 'Send Metrics' command. Takes over - * ownership of the passed LLSD pointer. + * ownership of the passed LLViewerAssetStats pointer. * * Thread: Thread1 (TextureFetch) */ @@ -2893,33 +2908,36 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) static volatile bool reporting_started(false); static volatile S32 report_sequence(0); - // We've already taken over ownership of the LLSD at this point - // and can do normal LLSD sharing operations at this point. But - // still being careful, regardless. - LLSD & main_stats = *mReportMain; - - LLSD thread1_stats = gViewerAssetStatsThread1->asLLSD(); // 'duration' & 'regions' from this LLSD - thread1_stats["message"] = "ViewerAssetMetrics"; // Identifies the type of metrics - thread1_stats["sequence"] = report_sequence; // Sequence number - thread1_stats["initial"] = ! reporting_started; // Initial data from viewer - thread1_stats["break"] = LLTextureFetch::svMetricsDataBreak; // Break in data prior to this report + // We've taken over ownership of the stats copy at this + // point. Get a working reference to it for merging here + // but leave it in 'this'. Destructor will rid us of it. + LLViewerAssetStats & main_stats = *mMainStats; + + // Merge existing stats into those from main, convert to LLSD + main_stats.merge(*gViewerAssetStatsThread1); + LLSD merged_llsd = main_stats.asLLSD(); + + // Add some additional meta fields to the content + merged_llsd["session_id"] = mSessionID; + merged_llsd["agent_id"] = mAgentID; + merged_llsd["message"] = "ViewerAssetMetrics"; // Identifies the type of metrics + merged_llsd["sequence"] = report_sequence; // Sequence number + merged_llsd["initial"] = ! reporting_started; // Initial data from viewer + merged_llsd["break"] = LLTextureFetch::svMetricsDataBreak; // Break in data prior to this report // Update sequence number if (S32_MAX == ++report_sequence) report_sequence = 0; - // Merge the two LLSDs into a single report - LLViewerAssetStatsFF::merge_stats(main_stats, thread1_stats); - // Limit the size of the stats report if necessary. - thread1_stats["truncated"] = truncate_viewer_metrics(10, thread1_stats); + merged_llsd["truncated"] = truncate_viewer_metrics(10, merged_llsd); if (! mCapsURL.empty()) { LLCurlRequest::headers_t headers; fetcher->getCurlRequest().post(mCapsURL, headers, - thread1_stats, + merged_llsd, new lcl_responder(report_sequence, report_sequence, LLTextureFetch::svMetricsDataBreak, @@ -2933,7 +2951,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) // In QA mode, Metrics submode, log the result for ease of testing if (fetcher->isQAMode()) { - LL_INFOS("Textures") << thread1_stats << LL_ENDL; + LL_INFOS("Textures") << merged_llsd << LL_ENDL; } gViewerAssetStatsThread1->reset(); diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index af30d1bb3b..a8fd3ce244 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -40,6 +40,8 @@ class HTTPGetResponder; class LLTextureCache; class LLImageDecodeThread; class LLHost; +class LLViewerAssetStats; + namespace { class TFRequest; } // Interface class @@ -88,7 +90,10 @@ public: // Commands available to other threads to control metrics gathering operations. void commandSetRegion(U64 region_handle); - void commandSendMetrics(const std::string & caps_url, LLSD * report_main); + void commandSendMetrics(const std::string & caps_url, + const LLUUID & session_id, + const LLUUID & agent_id, + LLViewerAssetStats * main_stats); void commandDataBreak(); LLCurlRequest & getCurlRequest() { return *mCurlGetRequest; } diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index d798786277..399d62d2fc 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -113,11 +113,34 @@ LLViewerAssetStats::PerRegionStats::reset() mRequests[i].mDequeued.reset(); mRequests[i].mResponse.reset(); } - + mFPS.reset(); + mTotalTime = 0; mStartTimestamp = LLViewerAssetStatsFF::get_timestamp(); } + +void +LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionStats & src) +{ + // mRegionHandle, mTotalTime, mStartTimestamp are left alone. + + // mFPS + if (src.mFPS.getCount() && mFPS.getCount()) + { + mFPS.merge(src.mFPS); + } + + // Requests + for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i) + { + mRequests[i].mEnqueued.merge(src.mRequests[i].mEnqueued); + mRequests[i].mDequeued.merge(src.mRequests[i].mDequeued); + mRequests[i].mResponse.merge(src.mRequests[i].mResponse); + } +} + + void LLViewerAssetStats::PerRegionStats::accumulateTime(duration_t now) { @@ -136,6 +159,19 @@ LLViewerAssetStats::LLViewerAssetStats() } +LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src) + : mRegionHandle(src.mRegionHandle), + mResetTimestamp(src.mResetTimestamp) +{ + const PerRegionContainer::const_iterator it_end(src.mRegionStats.end()); + for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it) + { + mRegionStats[it->first] = new PerRegionStats(*it->second); + } + mCurRegionStats = mRegionStats[mRegionHandle]; +} + + void LLViewerAssetStats::reset() { @@ -215,6 +251,12 @@ LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, bool with_htt mCurRegionStats->mRequests[int(eac)].mResponse.record(duration); } +void +LLViewerAssetStats::recordFPS(F32 fps) +{ + mCurRegionStats->mFPS.record(fps); +} + LLSD LLViewerAssetStats::asLLSD() { @@ -231,7 +273,7 @@ LLViewerAssetStats::asLLSD() LLSD::String("get_other") }; - // Sub-tags. If you add or delete from this list, mergeRegionsLLSD() must be updated. + // Stats Group Sub-tags. static const LLSD::String enq_tag("enqueued"); static const LLSD::String deq_tag("dequeued"); static const LLSD::String rcnt_tag("resp_count"); @@ -239,6 +281,12 @@ LLViewerAssetStats::asLLSD() static const LLSD::String rmax_tag("resp_max"); static const LLSD::String rmean_tag("resp_mean"); + // MMM Group Sub-tags. + static const LLSD::String cnt_tag("count"); + static const LLSD::String min_tag("min"); + static const LLSD::String max_tag("max"); + static const LLSD::String mean_tag("mean"); + const duration_t now = LLViewerAssetStatsFF::get_timestamp(); mCurRegionStats->accumulateTime(now); @@ -257,7 +305,7 @@ LLViewerAssetStats::asLLSD() LLSD reg_stat = LLSD::emptyMap(); - for (int i = 0; i < EVACCount; ++i) + for (int i = 0; i < LL_ARRAY_SIZE(tags); ++i) { LLSD & slot = reg_stat[tags[i]]; slot = LLSD::emptyMap(); @@ -269,6 +317,15 @@ LLViewerAssetStats::asLLSD() slot[rmean_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMean() * 1.0e-6)); } + { + LLSD & slot = reg_stat["fps"]; + slot = LLSD::emptyMap(); + slot[cnt_tag] = LLSD(S32(stats.mFPS.getCount())); + slot[min_tag] = LLSD(F64(stats.mFPS.getMin())); + slot[max_tag] = LLSD(F64(stats.mFPS.getMax())); + slot[mean_tag] = LLSD(F64(stats.mFPS.getMean())); + } + reg_stat["duration"] = LLSD::Real(stats.mTotalTime * 1.0e-6); std::stringstream reg_handle; reg_handle.width(16); @@ -284,181 +341,24 @@ LLViewerAssetStats::asLLSD() return ret; } -/* static */ void -LLViewerAssetStats::mergeRegionsLLSD(const LLSD & src, LLSD & dst) +void +LLViewerAssetStats::merge(const LLViewerAssetStats & src) { - // Merge operator definitions - static const int MOP_ADD_INT(0); - static const int MOP_MIN_REAL(1); - static const int MOP_MAX_REAL(2); - static const int MOP_MEAN_REAL(3); // Requires a 'mMergeOpArg' to weight the input terms - - static const LLSD::String regions_key("regions"); - static const LLSD::String resp_count_key("resp_count"); - - static const struct - { - LLSD::String mName; - int mMergeOp; - } - key_list[] = - { - // Order is important below. We modify the data in-place and - // so operations like MOP_MEAN_REAL which need the "resp_count" - // value for weighting must be performed before "resp_count" - // is modified or the weight will be wrong. Key list is - // defined in asLLSD() and must track it. - - { "resp_mean", MOP_MEAN_REAL }, - { "enqueued", MOP_ADD_INT }, - { "dequeued", MOP_ADD_INT }, - { "resp_min", MOP_MIN_REAL }, - { "resp_max", MOP_MAX_REAL }, - { resp_count_key, MOP_ADD_INT } // Keep last - }; + // mRegionHandle, mCurRegionStats and mResetTimestamp are left untouched. + // Just merge the stats bodies - // Trivial checks - if (! src.has(regions_key)) + const PerRegionContainer::const_iterator it_end(src.mRegionStats.end()); + for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it) { - return; - } - - if (! dst.has(regions_key)) - { - dst[regions_key] = src[regions_key]; - return; - } - - // Non-trivial cases requiring a deep merge. - const LLSD & root_src(src[regions_key]); - LLSD & root_dst(dst[regions_key]); - - const LLSD::map_const_iterator it_uuid_end(root_src.endMap()); - for (LLSD::map_const_iterator it_uuid(root_src.beginMap()); it_uuid_end != it_uuid; ++it_uuid) - { - if (! root_dst.has(it_uuid->first)) + PerRegionContainer::iterator dst(mRegionStats.find(it->first)); + if (mRegionStats.end() == dst) { - // src[] without matching dst[] - root_dst[it_uuid->first] = it_uuid->second; + // Destination is missing data, just make a private copy + mRegionStats[it->first] = new PerRegionStats(*it->second); } else { - // src[] with matching dst[] - // We have matching source and destination regions. - // Now iterate over each asset bin in the region status. Could iterate over - // an explicit list but this will do as well. - LLSD & reg_dst(root_dst[it_uuid->first]); - const LLSD & reg_src(root_src[it_uuid->first]); - - const LLSD::map_const_iterator it_sets_end(reg_src.endMap()); - for (LLSD::map_const_iterator it_sets(reg_src.beginMap()); it_sets_end != it_sets; ++it_sets) - { - static const LLSD::String no_touch_1("duration"); - - if (no_touch_1 == it_sets->first) - { - continue; - } - else if (! reg_dst.has(it_sets->first)) - { - // src[][] without matching dst[][] - reg_dst[it_sets->first] = it_sets->second; - } - else - { - // src[][] with matching dst[][] - // Matching stats bin in both source and destination regions. - // Iterate over those bin keys we know how to merge, leave the remainder untouched. - LLSD & bin_dst(reg_dst[it_sets->first]); - const LLSD & bin_src(reg_src[it_sets->first]); - - // The "resp_count" value is needed repeatedly in operations. - const LLSD::Integer bin_src_count(bin_src[resp_count_key].asInteger()); - const LLSD::Integer bin_dst_count(bin_dst[resp_count_key].asInteger()); - - for (int key_index(0); key_index < LL_ARRAY_SIZE(key_list); ++key_index) - { - const LLSD::String & key_name(key_list[key_index].mName); - - if (! bin_src.has(key_name)) - { - // Missing src[][][] - continue; - } - - const LLSD & src_value(bin_src[key_name]); - - if (! bin_dst.has(key_name)) - { - // src[][][] without matching dst[][][] - bin_dst[key_name] = src_value; - } - else - { - // src[][][] with matching dst[][][] - LLSD & dst_value(bin_dst[key_name]); - - switch (key_list[key_index].mMergeOp) - { - case MOP_ADD_INT: - // Simple counts, just add - dst_value = dst_value.asInteger() + src_value.asInteger(); - break; - - case MOP_MIN_REAL: - // Minimum - if (bin_src_count) - { - // If src has non-zero count, it's min is meaningful - if (bin_dst_count) - { - dst_value = llmin(dst_value.asReal(), src_value.asReal()); - } - else - { - dst_value = src_value; - } - } - break; - - case MOP_MAX_REAL: - // Maximum - if (bin_src_count) - { - // If src has non-zero count, it's max is meaningful - if (bin_dst_count) - { - dst_value = llmax(dst_value.asReal(), src_value.asReal()); - } - else - { - dst_value = src_value; - } - } - break; - - case MOP_MEAN_REAL: - { - // Mean - F64 src_weight(bin_src_count); - F64 dst_weight(bin_dst_count); - F64 tot_weight(src_weight + dst_weight); - if (tot_weight >= F64(0.5)) - { - dst_value = (((dst_value.asReal() * dst_weight) - + (src_value.asReal() * src_weight)) - / tot_weight); - } - } - break; - - default: - break; - } - } - } - } - } + dst->second->merge(*it->second); } } } @@ -526,6 +426,15 @@ record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, gViewerAssetStatsMain->recordGetServiced(at, with_http, is_temp, duration); } +void +record_fps_main(F32 fps) +{ + if (! gViewerAssetStatsMain) + return; + + gViewerAssetStatsMain->recordFPS(fps); +} + // 'thread1' - should be for TextureFetch thread @@ -590,41 +499,6 @@ cleanup() } -void -merge_stats(const LLSD & src, LLSD & dst) -{ - static const LLSD::String regions_key("regions"); - - // Trivial cases first - if (! src.isMap()) - { - return; - } - - if (! dst.isMap()) - { - dst = src; - return; - } - - // Okay, both src and dst are maps at this point. - // Collector class know how to merge the regions part. - LLViewerAssetStats::mergeRegionsLLSD(src, dst); - - // Now merge non-regions bits manually. - const LLSD::map_const_iterator it_end(src.endMap()); - for (LLSD::map_const_iterator it(src.beginMap()); it_end != it; ++it) - { - if (regions_key == it->first) - continue; - - if (dst.has(it->first)) - continue; - - dst[it->first] = it->second; - } -} - } // namespace LLViewerAssetStatsFF diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index ed2d0f3922..af6bf5b695 100644 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -125,29 +125,48 @@ public: { reset(); } + + PerRegionStats(const PerRegionStats & src) + : LLRefCount(), + mRegionHandle(src.mRegionHandle), + mTotalTime(src.mTotalTime), + mStartTimestamp(src.mStartTimestamp), + mFPS(src.mFPS) + { + for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i) + { + mRequests[i] = src.mRequests[i]; + } + } + // Default assignment and destructor are correct. void reset(); + void merge(const PerRegionStats & src); + // Apply current running time to total and reset start point. // Return current timestamp as a convenience. void accumulateTime(duration_t now); public: - region_handle_t mRegionHandle; - duration_t mTotalTime; - duration_t mStartTimestamp; + region_handle_t mRegionHandle; + duration_t mTotalTime; + duration_t mStartTimestamp; + LLSimpleStatMMM<> mFPS; struct { LLSimpleStatCounter mEnqueued; LLSimpleStatCounter mDequeued; LLSimpleStatMMM mResponse; - } mRequests [EVACCount]; + } + mRequests [EVACCount]; }; public: LLViewerAssetStats(); + LLViewerAssetStats(const LLViewerAssetStats &); // Default destructor is correct. LLViewerAssetStats & operator=(const LLViewerAssetStats &); // Not defined @@ -165,6 +184,18 @@ public: void recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp); void recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, duration_t duration); + // Frames-Per-Second Samples + void recordFPS(F32 fps); + + // Merge a source instance into a destination instance. This is + // conceptually an 'operator+=()' method: + // - counts are added + // - minimums are min'd + // - maximums are max'd + // - other scalars are ignored ('this' wins) + // + void merge(const LLViewerAssetStats & src); + // Retrieve current metrics for all visited regions (NULL region UUID/handle excluded) // Returned LLSD is structured as follows: // @@ -177,11 +208,19 @@ public: // resp_mean : float // } // + // &mmm_group = { + // count : int, + // min : float, + // max : float, + // mean : float + // } + // // { // duration: int // regions: { // $: { // Keys are strings of the region's handle in hex // duration: : int, + // fps: : &mmm_group, // get_texture_temp_http : &stats_group, // get_texture_temp_udp : &stats_group, // get_texture_non_temp_http : &stats_group, @@ -195,15 +234,6 @@ public: // } LLSD asLLSD(); - // Merges the "regions" maps in two LLSDs structured as per asLLSD(). - // This takes two LLSDs as returned by asLLSD() and intelligently - // merges the metrics contained in the maps indexed by "regions". - // The remainder of the top-level map of the LLSDs is left unchanged - // in expectation that callers will add other information at this - // level. The "regions" information must be correctly formed or the - // final result is undefined (little defensive action). - static void mergeRegionsLLSD(const LLSD & src, LLSD & dst); - protected: typedef std::map > PerRegionContainer; @@ -278,6 +308,8 @@ void record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_te void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration); +void record_fps_main(F32 fps); + /** * Region context, event and duration loggers for Thread 1. @@ -291,18 +323,6 @@ void record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is void record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration); -/** - * @brief Merge two LLSD reports from different collector instances - * - * Use this to merge the LLSD's from two threads. For top-level, - * non-region data the destination (dst) is considered authoritative - * if the key is present in both source and destination. For - * regions, a numerical merge is performed when data are present in - * both source and destination and the 'right thing' is done for - * counts, minimums, maximums and averages. - */ -void merge_stats(const LLSD & src, LLSD & dst); - } // namespace LLViewerAssetStatsFF #endif // LL_LLVIEWERASSETSTATUS_H diff --git a/indra/newview/tests/llsimplestat_test.cpp b/indra/newview/tests/llsimplestat_test.cpp index 5efc9cf857..60a8cac995 100644 --- a/indra/newview/tests/llsimplestat_test.cpp +++ b/indra/newview/tests/llsimplestat_test.cpp @@ -425,4 +425,162 @@ namespace tut ensure("Overflowed MMM has huge max", (bignum == m1.getMax())); ensure("Overflowed MMM has fetchable mean", (zero == m1.getMean() || true)); } + + // Testing LLSimpleStatCounter's merge() method + template<> template<> + void stat_counter_index_object_t::test<12>() + { + LLSimpleStatCounter c1; + LLSimpleStatCounter c2; + + ++c1; + ++c1; + ++c1; + ++c1; + + ++c2; + ++c2; + c2.merge(c1); + + ensure_equals("4 merged into 2 results in 6", 6, c2.getCount()); + + ensure_equals("Source of merge is undamaged", 4, c1.getCount()); + } + + // Testing LLSimpleStatMMM's merge() method + template<> template<> + void stat_counter_index_object_t::test<13>() + { + LLSimpleStatMMM<> m1; + LLSimpleStatMMM<> m2; + + m1.record(3.5); + m1.record(4.5); + m1.record(5.5); + m1.record(6.5); + + m2.record(5.0); + m2.record(7.0); + m2.record(9.0); + + m2.merge(m1); + + ensure_equals("Count after merge (p1)", 7, m2.getCount()); + ensure_approximately_equals("Min after merge (p1)", F32(3.5), m2.getMin(), 22); + ensure_approximately_equals("Max after merge (p1)", F32(9.0), m2.getMax(), 22); + ensure_approximately_equals("Mean after merge (p1)", F32(41.000/7.000), m2.getMean(), 22); + + + ensure_equals("Source count of merge is undamaged (p1)", 4, m1.getCount()); + ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(3.5), m1.getMin(), 22); + ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(6.5), m1.getMax(), 22); + ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(5.0), m1.getMean(), 22); + + m2.reset(); + + m2.record(-22.0); + m2.record(-1.0); + m2.record(30.0); + + m2.merge(m1); + + ensure_equals("Count after merge (p2)", 7, m2.getCount()); + ensure_approximately_equals("Min after merge (p2)", F32(-22.0), m2.getMin(), 22); + ensure_approximately_equals("Max after merge (p2)", F32(30.0), m2.getMax(), 22); + ensure_approximately_equals("Mean after merge (p2)", F32(27.000/7.000), m2.getMean(), 22); + + } + + // Testing LLSimpleStatMMM's merge() method when src contributes nothing + template<> template<> + void stat_counter_index_object_t::test<14>() + { + LLSimpleStatMMM<> m1; + LLSimpleStatMMM<> m2; + + m2.record(5.0); + m2.record(7.0); + m2.record(9.0); + + m2.merge(m1); + + ensure_equals("Count after merge (p1)", 3, m2.getCount()); + ensure_approximately_equals("Min after merge (p1)", F32(5.0), m2.getMin(), 22); + ensure_approximately_equals("Max after merge (p1)", F32(9.0), m2.getMax(), 22); + ensure_approximately_equals("Mean after merge (p1)", F32(7.000), m2.getMean(), 22); + + ensure_equals("Source count of merge is undamaged (p1)", 0, m1.getCount()); + ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(0), m1.getMin(), 22); + ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(0), m1.getMax(), 22); + ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(0), m1.getMean(), 22); + + m2.reset(); + + m2.record(-22.0); + m2.record(-1.0); + + m2.merge(m1); + + ensure_equals("Count after merge (p2)", 2, m2.getCount()); + ensure_approximately_equals("Min after merge (p2)", F32(-22.0), m2.getMin(), 22); + ensure_approximately_equals("Max after merge (p2)", F32(-1.0), m2.getMax(), 22); + ensure_approximately_equals("Mean after merge (p2)", F32(-11.5), m2.getMean(), 22); + } + + // Testing LLSimpleStatMMM's merge() method when dst contributes nothing + template<> template<> + void stat_counter_index_object_t::test<15>() + { + LLSimpleStatMMM<> m1; + LLSimpleStatMMM<> m2; + + m1.record(5.0); + m1.record(7.0); + m1.record(9.0); + + m2.merge(m1); + + ensure_equals("Count after merge (p1)", 3, m2.getCount()); + ensure_approximately_equals("Min after merge (p1)", F32(5.0), m2.getMin(), 22); + ensure_approximately_equals("Max after merge (p1)", F32(9.0), m2.getMax(), 22); + ensure_approximately_equals("Mean after merge (p1)", F32(7.000), m2.getMean(), 22); + + ensure_equals("Source count of merge is undamaged (p1)", 3, m1.getCount()); + ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(5.0), m1.getMin(), 22); + ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(9.0), m1.getMax(), 22); + ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(7.0), m1.getMean(), 22); + + m1.reset(); + m2.reset(); + + m1.record(-22.0); + m1.record(-1.0); + + m2.merge(m1); + + ensure_equals("Count after merge (p2)", 2, m2.getCount()); + ensure_approximately_equals("Min after merge (p2)", F32(-22.0), m2.getMin(), 22); + ensure_approximately_equals("Max after merge (p2)", F32(-1.0), m2.getMax(), 22); + ensure_approximately_equals("Mean after merge (p2)", F32(-11.5), m2.getMean(), 22); + } + + // Testing LLSimpleStatMMM's merge() method when neither dst nor src contributes + template<> template<> + void stat_counter_index_object_t::test<16>() + { + LLSimpleStatMMM<> m1; + LLSimpleStatMMM<> m2; + + m2.merge(m1); + + ensure_equals("Count after merge (p1)", 0, m2.getCount()); + ensure_approximately_equals("Min after merge (p1)", F32(0), m2.getMin(), 22); + ensure_approximately_equals("Max after merge (p1)", F32(0), m2.getMax(), 22); + ensure_approximately_equals("Mean after merge (p1)", F32(0), m2.getMean(), 22); + + ensure_equals("Source count of merge is undamaged (p1)", 0, m1.getCount()); + ensure_approximately_equals("Source min of merge is undamaged (p1)", F32(0), m1.getMin(), 22); + ensure_approximately_equals("Source max of merge is undamaged (p1)", F32(0), m1.getMax(), 22); + ensure_approximately_equals("Source mean of merge is undamaged (p1)", F32(0), m1.getMean(), 22); + } } diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index 153056b3cd..9c54266017 100644 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -44,6 +44,7 @@ static const char * all_keys[] = { "duration", + "fps", "get_other", "get_texture_temp_http", "get_texture_temp_udp", @@ -76,6 +77,19 @@ static const char * sub_keys[] = "resp_mean" }; +static const char * mmm_resp_keys[] = +{ + "fps" +}; + +static const char * mmm_sub_keys[] = +{ + "count", + "max", + "min", + "mean" +}; + static const LLUUID region1("4e2d81a3-6263-6ffe-ad5c-8ce04bee07e8"); static const LLUUID region2("68762cc8-b68b-4e45-854b-e830734f2d4a"); static const U64 region1_handle(0x00000401000003f7ULL); @@ -172,6 +186,15 @@ namespace tut ensure(line, sd[resp_keys[i]].has(sub_keys[j])); } } + + for (int i = 0; i < LL_ARRAY_SIZE(mmm_resp_keys); ++i) + { + for (int j = 0; j < LL_ARRAY_SIZE(mmm_sub_keys); ++j) + { + std::string line = llformat("Key '%s' has '%s' key", mmm_resp_keys[i], mmm_sub_keys[j]); + ensure(line, sd[mmm_resp_keys[i]].has(mmm_sub_keys[j])); + } + } } // Create a non-global instance and check some content @@ -461,293 +484,395 @@ namespace tut ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); } - // Check that the LLSD merger knows what it's doing (basic test) + + // LLViewerAssetStats::merge() basic functions work template<> template<> void tst_viewerassetstats_index_object_t::test<9>() { - LLSD::String reg1_name = region1_handle_str; - LLSD::String reg2_name = region2_handle_str; - - LLSD reg1_stats = LLSD::emptyMap(); - LLSD reg2_stats = LLSD::emptyMap(); - - LLSD & tmp_other1 = reg1_stats["get_other"]; - tmp_other1["enqueued"] = 4; - tmp_other1["dequeued"] = 4; - tmp_other1["resp_count"] = 8; - tmp_other1["resp_max"] = F64(23.2892); - tmp_other1["resp_min"] = F64(0.2829); - tmp_other1["resp_mean"] = F64(2.298928); - - LLSD & tmp_other2 = reg2_stats["get_other"]; - tmp_other2["enqueued"] = 8; - tmp_other2["dequeued"] = 7; - tmp_other2["resp_count"] = 3; - tmp_other2["resp_max"] = F64(6.5); - tmp_other2["resp_min"] = F64(0.01); - tmp_other2["resp_mean"] = F64(4.1); + LLViewerAssetStats s1; + LLViewerAssetStats s2; + + s1.setRegion(region1_handle); + s2.setRegion(region1_handle); + + s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 5000000); + s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 6000000); + s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 8000000); + s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 7000000); + s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 9000000); - { - LLSD src = LLSD::emptyMap(); - LLSD dst = LLSD::emptyMap(); + s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 2000000); + s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 3000000); + s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 4000000); - src["regions"][reg1_name] = reg1_stats; - src["duration"] = 24; - dst["regions"][reg2_name] = reg2_stats; - dst["duration"] = 36; + s2.merge(s1); - LLViewerAssetStats::mergeRegionsLLSD(src, dst); + LLSD s2_llsd = s2.asLLSD(); - ensure("region 1 in merged stats", llsd_equals(reg1_stats, dst["regions"][reg1_name])); - ensure("region 2 still in merged stats", llsd_equals(reg2_stats, dst["regions"][reg2_name])); - } + ensure_equals("count after merge", 8, s2_llsd["regions"][region1_handle_str]["get_texture_temp_http"]["resp_count"].asInteger()); + ensure_approximately_equals("min after merge", 2.0, s2_llsd["regions"][region1_handle_str]["get_texture_temp_http"]["resp_min"].asReal(), 22); + ensure_approximately_equals("max after merge", 9.0, s2_llsd["regions"][region1_handle_str]["get_texture_temp_http"]["resp_max"].asReal(), 22); + ensure_approximately_equals("max after merge", 5.5, s2_llsd["regions"][region1_handle_str]["get_texture_temp_http"]["resp_mean"].asReal(), 22); - { - LLSD src = LLSD::emptyMap(); - LLSD dst = LLSD::emptyMap(); - - src["regions"][reg1_name] = reg1_stats; - src["duration"] = 24; - dst["regions"][reg1_name] = reg2_stats; - dst["duration"] = 36; - - LLViewerAssetStats::mergeRegionsLLSD(src, dst); - - ensure("src not ruined", llsd_equals(reg1_stats, src["regions"][reg1_name])); - ensure_equals("added enqueued counts", dst["regions"][reg1_name]["get_other"]["enqueued"].asInteger(), 12); - ensure_equals("added dequeued counts", dst["regions"][reg1_name]["get_other"]["dequeued"].asInteger(), 11); - ensure_equals("added response counts", dst["regions"][reg1_name]["get_other"]["resp_count"].asInteger(), 11); - ensure_approximately_equals("min'd minimum response times", dst["regions"][reg1_name]["get_other"]["resp_min"].asReal(), 0.01, 20); - ensure_approximately_equals("max'd maximum response times", dst["regions"][reg1_name]["get_other"]["resp_max"].asReal(), 23.2892, 20); - ensure_approximately_equals("weighted mean of means", dst["regions"][reg1_name]["get_other"]["resp_mean"].asReal(), 2.7901295, 20); - } } - // Maximum merges are interesting when one side contributes nothing + // LLViewerAssetStats::merge() basic functions work without corrupting source data template<> template<> void tst_viewerassetstats_index_object_t::test<10>() { - LLSD::String reg1_name = region1_handle_str; - LLSD::String reg2_name = region2_handle_str; - - LLSD reg1_stats = LLSD::emptyMap(); - LLSD reg2_stats = LLSD::emptyMap(); - - LLSD & tmp_other1 = reg1_stats["get_other"]; - tmp_other1["enqueued"] = 4; - tmp_other1["dequeued"] = 4; - tmp_other1["resp_count"] = 7; - tmp_other1["resp_max"] = F64(-23.2892); - tmp_other1["resp_min"] = F64(-123.2892); - tmp_other1["resp_mean"] = F64(-58.28298); - - LLSD & tmp_other2 = reg2_stats["get_other"]; - tmp_other2["enqueued"] = 8; - tmp_other2["dequeued"] = 7; - tmp_other2["resp_count"] = 0; - tmp_other2["resp_max"] = F64(0); - tmp_other2["resp_min"] = F64(0); - tmp_other2["resp_mean"] = F64(0); - - { - LLSD src = LLSD::emptyMap(); - LLSD dst = LLSD::emptyMap(); + LLViewerAssetStats s1; + LLViewerAssetStats s2; - src["regions"][reg1_name] = reg1_stats; - src["duration"] = 24; - dst["regions"][reg1_name] = reg2_stats; - dst["duration"] = 36; + s1.setRegion(region1_handle); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - LLViewerAssetStats::mergeRegionsLLSD(src, dst); - - ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum", - dst["regions"][reg1_name]["get_other"]["resp_max"].asReal(), F64(-23.2892), 20); - } - - { - LLSD src = LLSD::emptyMap(); - LLSD dst = LLSD::emptyMap(); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - src["regions"][reg1_name] = reg2_stats; - src["duration"] = 24; - dst["regions"][reg1_name] = reg1_stats; - dst["duration"] = 36; + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 23289200); + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 282900); - LLViewerAssetStats::mergeRegionsLLSD(src, dst); - ensure_approximately_equals("src maximum with count 0 does not contribute to merged maximum", - dst["regions"][reg1_name]["get_other"]["resp_max"].asReal(), F64(-23.2892), 20); - } - } + s2.setRegion(region2_handle); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 6500000); + s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 10000); - // Minimum merges are interesting when one side contributes nothing - template<> template<> - void tst_viewerassetstats_index_object_t::test<11>() - { - LLSD::String reg1_name = region1_handle_str; - LLSD::String reg2_name = region2_handle_str; - - LLSD reg1_stats = LLSD::emptyMap(); - LLSD reg2_stats = LLSD::emptyMap(); - - LLSD & tmp_other1 = reg1_stats["get_other"]; - tmp_other1["enqueued"] = 4; - tmp_other1["dequeued"] = 4; - tmp_other1["resp_count"] = 7; - tmp_other1["resp_max"] = F64(123.2892); - tmp_other1["resp_min"] = F64(23.2892); - tmp_other1["resp_mean"] = F64(58.28298); - - LLSD & tmp_other2 = reg2_stats["get_other"]; - tmp_other2["enqueued"] = 8; - tmp_other2["dequeued"] = 7; - tmp_other2["resp_count"] = 0; - tmp_other2["resp_max"] = F64(0); - tmp_other2["resp_min"] = F64(0); - tmp_other2["resp_mean"] = F64(0); - { - LLSD src = LLSD::emptyMap(); - LLSD dst = LLSD::emptyMap(); - - src["regions"][reg1_name] = reg1_stats; - src["duration"] = 24; - dst["regions"][reg1_name] = reg2_stats; - dst["duration"] = 36; + s2.merge(s1); + + LLSD src = s1.asLLSD(); + LLSD dst = s2.asLLSD(); + + // Remove time stamps, they're a problem + src.erase("duration"); + src["regions"][region1_handle_str].erase("duration"); + dst.erase("duration"); + dst["regions"][region1_handle_str].erase("duration"); + dst["regions"][region2_handle_str].erase("duration"); + + ensure_equals("merge src has single region", 1, src["regions"].size()); + ensure_equals("merge dst has dual regions", 2, dst["regions"].size()); + ensure("result from src is in dst", llsd_equals(src["regions"][region1_handle_str], + dst["regions"][region1_handle_str])); + } - LLViewerAssetStats::mergeRegionsLLSD(src, dst); + s1.setRegion(region1_handle); + s2.setRegion(region1_handle); + s1.reset(); + s2.reset(); - ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum", - dst["regions"][reg1_name]["get_other"]["resp_min"].asReal(), F64(23.2892), 20); - } + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - { - LLSD src = LLSD::emptyMap(); - LLSD dst = LLSD::emptyMap(); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - src["regions"][reg1_name] = reg2_stats; - src["duration"] = 24; - dst["regions"][reg1_name] = reg1_stats; - dst["duration"] = 36; + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 23289200); + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 282900); - LLViewerAssetStats::mergeRegionsLLSD(src, dst); - ensure_approximately_equals("src minimum with count 0 does not contribute to merged minimum", - dst["regions"][reg1_name]["get_other"]["resp_min"].asReal(), F64(23.2892), 20); + s2.setRegion(region1_handle); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 6500000); + s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 10000); + + { + s2.merge(s1); + + LLSD src = s1.asLLSD(); + LLSD dst = s2.asLLSD(); + + // Remove time stamps, they're a problem + src.erase("duration"); + src["regions"][region1_handle_str].erase("duration"); + dst.erase("duration"); + dst["regions"][region1_handle_str].erase("duration"); + + ensure_equals("src counts okay (enq)", 4, src["regions"][region1_handle_str]["get_other"]["enqueued"].asInteger()); + ensure_equals("src counts okay (deq)", 4, src["regions"][region1_handle_str]["get_other"]["dequeued"].asInteger()); + ensure_equals("src resp counts okay", 2, src["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); + ensure_approximately_equals("src respmin okay", 0.2829, src["regions"][region1_handle_str]["get_other"]["resp_min"].asReal(), 20); + ensure_approximately_equals("src respmax okay", 23.2892, src["regions"][region1_handle_str]["get_other"]["resp_max"].asReal(), 20); + + ensure_equals("dst counts okay (enq)", 12, dst["regions"][region1_handle_str]["get_other"]["enqueued"].asInteger()); + ensure_equals("src counts okay (deq)", 11, dst["regions"][region1_handle_str]["get_other"]["dequeued"].asInteger()); + ensure_equals("dst resp counts okay", 4, dst["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); + ensure_approximately_equals("dst respmin okay", 0.010, dst["regions"][region1_handle_str]["get_other"]["resp_min"].asReal(), 20); + ensure_approximately_equals("dst respmax okay", 23.2892, dst["regions"][region1_handle_str]["get_other"]["resp_max"].asReal(), 20); } } - // resp_count missing is taken as '0' for maximum calculation + + // Maximum merges are interesting when one side contributes nothing template<> template<> - void tst_viewerassetstats_index_object_t::test<12>() + void tst_viewerassetstats_index_object_t::test<11>() { - LLSD::String reg1_name = region1_handle_str; - LLSD::String reg2_name = region2_handle_str; - - LLSD reg1_stats = LLSD::emptyMap(); - LLSD reg2_stats = LLSD::emptyMap(); - - LLSD & tmp_other1 = reg1_stats["get_other"]; - tmp_other1["enqueued"] = 4; - tmp_other1["dequeued"] = 4; - tmp_other1["resp_count"] = 7; - tmp_other1["resp_max"] = F64(-23.2892); - tmp_other1["resp_min"] = F64(-123.2892); - tmp_other1["resp_mean"] = F64(-58.28298); - - LLSD & tmp_other2 = reg2_stats["get_other"]; - tmp_other2["enqueued"] = 8; - tmp_other2["dequeued"] = 7; - // tmp_other2["resp_count"] = 0; - tmp_other2["resp_max"] = F64(0); - tmp_other2["resp_min"] = F64(0); - tmp_other2["resp_mean"] = F64(0); - + LLViewerAssetStats s1; + LLViewerAssetStats s2; + + s1.setRegion(region1_handle); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + // Want to test negative numbers here but have to work in U64 + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); + + s2.setRegion(region1_handle); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + { - LLSD src = LLSD::emptyMap(); - LLSD dst = LLSD::emptyMap(); + s2.merge(s1); + + LLSD src = s1.asLLSD(); + LLSD dst = s2.asLLSD(); - src["regions"][reg1_name] = reg1_stats; - src["duration"] = 24; - dst["regions"][reg1_name] = reg2_stats; - dst["duration"] = 36; + // Remove time stamps, they're a problem + src.erase("duration"); + src["regions"][region1_handle_str].erase("duration"); + dst.erase("duration"); + dst["regions"][region1_handle_str].erase("duration"); - LLViewerAssetStats::mergeRegionsLLSD(src, dst); - - ensure_approximately_equals("dst maximum with undefined count does not contribute to merged maximum", - dst["regions"][reg1_name]["get_other"]["resp_max"].asReal(), F64(-23.2892), 20); + ensure_equals("dst counts come from src only", 3, dst["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); + + ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum", + dst["regions"][region1_handle_str]["get_other"]["resp_max"].asReal(), F64(0.0), 20); } + // Other way around + s1.setRegion(region1_handle); + s2.setRegion(region1_handle); + s1.reset(); + s2.reset(); + + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + // Want to test negative numbers here but have to work in U64 + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); + + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + { - LLSD src = LLSD::emptyMap(); - LLSD dst = LLSD::emptyMap(); + s1.merge(s2); + + LLSD src = s2.asLLSD(); + LLSD dst = s1.asLLSD(); - src["regions"][reg1_name] = reg2_stats; - src["duration"] = 24; - dst["regions"][reg1_name] = reg1_stats; - dst["duration"] = 36; + // Remove time stamps, they're a problem + src.erase("duration"); + src["regions"][region1_handle_str].erase("duration"); + dst.erase("duration"); + dst["regions"][region1_handle_str].erase("duration"); - LLViewerAssetStats::mergeRegionsLLSD(src, dst); - - ensure_approximately_equals("src maximum with undefined count does not contribute to merged maximum", - dst["regions"][reg1_name]["get_other"]["resp_max"].asReal(), F64(-23.2892), 20); + ensure_equals("dst counts come from src only (flipped)", 3, dst["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); + + ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum (flipped)", + dst["regions"][region1_handle_str]["get_other"]["resp_max"].asReal(), F64(0.0), 20); } } - // resp_count unspecified is taken as 0 for minimum merges + // Minimum merges are interesting when one side contributes nothing template<> template<> - void tst_viewerassetstats_index_object_t::test<13>() + void tst_viewerassetstats_index_object_t::test<12>() { - LLSD::String reg1_name = region1.asString(); - LLSD::String reg2_name = region2.asString(); - - LLSD reg1_stats = LLSD::emptyMap(); - LLSD reg2_stats = LLSD::emptyMap(); - - LLSD & tmp_other1 = reg1_stats["get_other"]; - tmp_other1["enqueued"] = 4; - tmp_other1["dequeued"] = 4; - tmp_other1["resp_count"] = 7; - tmp_other1["resp_max"] = F64(123.2892); - tmp_other1["resp_min"] = F64(23.2892); - tmp_other1["resp_mean"] = F64(58.28298); - - LLSD & tmp_other2 = reg2_stats["get_other"]; - tmp_other2["enqueued"] = 8; - tmp_other2["dequeued"] = 7; - // tmp_other2["resp_count"] = 0; - tmp_other2["resp_max"] = F64(0); - tmp_other2["resp_min"] = F64(0); - tmp_other2["resp_mean"] = F64(0); - + LLViewerAssetStats s1; + LLViewerAssetStats s2; + + s1.setRegion(region1_handle); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 3800000); + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2700000); + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2900000); + + s2.setRegion(region1_handle); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + { - LLSD src = LLSD::emptyMap(); - LLSD dst = LLSD::emptyMap(); + s2.merge(s1); + + LLSD src = s1.asLLSD(); + LLSD dst = s2.asLLSD(); - src["regions"][reg1_name] = reg1_stats; - src["duration"] = 24; - dst["regions"][reg1_name] = reg2_stats; - dst["duration"] = 36; + // Remove time stamps, they're a problem + src.erase("duration"); + src["regions"][region1_handle_str].erase("duration"); + dst.erase("duration"); + dst["regions"][region1_handle_str].erase("duration"); - LLViewerAssetStats::mergeRegionsLLSD(src, dst); - - ensure_approximately_equals("dst minimum with undefined count does not contribute to merged minimum", - dst["regions"][reg1_name]["get_other"]["resp_min"].asReal(), F64(23.2892), 20); + ensure_equals("dst counts come from src only", 3, dst["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); + + ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum", + dst["regions"][region1_handle_str]["get_other"]["resp_min"].asReal(), F64(2.7), 20); } + // Other way around + s1.setRegion(region1_handle); + s2.setRegion(region1_handle); + s1.reset(); + s2.reset(); + + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 3800000); + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2700000); + s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2900000); + + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + { - LLSD src = LLSD::emptyMap(); - LLSD dst = LLSD::emptyMap(); + s1.merge(s2); + + LLSD src = s2.asLLSD(); + LLSD dst = s1.asLLSD(); - src["regions"][reg1_name] = reg2_stats; - src["duration"] = 24; - dst["regions"][reg1_name] = reg1_stats; - dst["duration"] = 36; + // Remove time stamps, they're a problem + src.erase("duration"); + src["regions"][region1_handle_str].erase("duration"); + dst.erase("duration"); + dst["regions"][region1_handle_str].erase("duration"); - LLViewerAssetStats::mergeRegionsLLSD(src, dst); - - ensure_approximately_equals("src minimum with undefined count does not contribute to merged minimum", - dst["regions"][reg1_name]["get_other"]["resp_min"].asReal(), F64(23.2892), 20); + ensure_equals("dst counts come from src only (flipped)", 3, dst["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); + + ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum (flipped)", + dst["regions"][region1_handle_str]["get_other"]["resp_min"].asReal(), F64(2.7), 20); } } + } -- cgit v1.2.3 From e58965255d1edcb44256e1b27d813167df746034 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Fri, 10 Dec 2010 18:31:38 -0800 Subject: CHOP-260 implementation. Update Ready notification gets real UI. reviewed by Mani. --- indra/newview/llappviewer.cpp | 78 +++++++++++++--------- .../newview/skins/default/xui/en/notifications.xml | 12 ++-- 2 files changed, 53 insertions(+), 37 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 5bd0a0d297..eb8d87e184 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2417,55 +2417,71 @@ namespace { LLUpdaterService().startChecking(install_if_ready); } - void on_required_update_downloaded(LLSD const & data) + void on_update_downloaded(LLSD const & data) { std::string notification_name; - if(LLStartUp::getStartupState() <= STATE_LOGIN_WAIT) + void (*apply_callback)(LLSD const &, LLSD const &) = NULL; + + if(data["required"].asBoolean()) { - // The user never saw the progress bar. - notification_name = "RequiredUpdateDownloadedVerboseDialog"; + apply_callback = &apply_update_ok_callback; + if(LLStartUp::getStartupState() <= STATE_LOGIN_WAIT) + { + // The user never saw the progress bar. + notification_name = "RequiredUpdateDownloadedVerboseDialog"; + } + else + { + notification_name = "RequiredUpdateDownloadedDialog"; + } } else { - notification_name = "RequiredUpdateDownloadedDialog"; + apply_callback = &apply_update_callback; + if(LLStartUp::getStartupState() < STATE_STARTED) + { + // CHOP-262 we need to use a different notification + // method prior to login. + notification_name = "DownloadBackgroundDialog"; + } + else + { + notification_name = "DownloadBackgroundTip"; + } } + LLSD substitutions; substitutions["VERSION"] = data["version"]; - LLNotificationsUtil::add(notification_name, substitutions, LLSD(), &apply_update_ok_callback); - } - - void on_optional_update_downloaded(LLSD const & data) - { - std::string notification_name; - if(LLStartUp::getStartupState() < STATE_STARTED) - { - // CHOP-262 we need to use a different notification - // method prior to login. - notification_name = "DownloadBackgroundDialog"; - } - else + + // truncate version at the rightmost '.' + std::string version_short(data["version"]); + size_t short_length = version_short.rfind('.'); + if (short_length != std::string::npos) { - notification_name = "DownloadBackgroundTip"; + version_short.resize(short_length); } - LLSD substitutions; - substitutions["VERSION"] = data["version"]; - LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_update_callback); - } + LLUIString relnotes_url("[RELEASE_NOTES_BASE_URL][CHANNEL_URL]/[VERSION_SHORT]"); + relnotes_url.setArg("[VERSION_SHORT]", version_short); + + // *TODO thread the update service's response through to this point + std::string const & channel = LLVersionInfo::getChannel(); + boost::shared_ptr channel_escaped(curl_escape(channel.c_str(), channel.size()), &curl_free); + + relnotes_url.setArg("[CHANNEL_URL]", channel_escaped.get()); + relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL")); + substitutions["RELEASE_NOTES_FULL_URL"] = relnotes_url.getString(); + + LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_callback); + } + bool notify_update(LLSD const & evt) { std::string notification_name; switch (evt["type"].asInteger()) { case LLUpdaterService::DOWNLOAD_COMPLETE: - if(evt["required"].asBoolean()) - { - on_required_update_downloaded(evt); - } - else - { - on_optional_update_downloaded(evt); - } + on_update_downloaded(evt); break; case LLUpdaterService::INSTALL_ERROR: LLNotificationsUtil::add("FailedUpdateInstall"); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index eecbeeb8dc..b0bb93c13a 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -2906,20 +2906,20 @@ or you can install it now. icon="notify.tga" name="DownloadBackgroundTip" type="notify"> -We have downloaded and update to your [APP_NAME] installation. -Version [VERSION] +We have downloaded an update to your [APP_NAME] installation. +Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update] + notext="Later..." + yestext="Install now and restart [APP_NAME]"/> -We have downloaded and update to your [APP_NAME] installation. -Version [VERSION] +We have downloaded an update to your [APP_NAME] installation. +Version [VERSION] [[RELEASE_NOTES_FULL_URL] Information about this update] Date: Sat, 11 Dec 2010 16:16:07 -0500 Subject: ESC-211 ESC-212 Use arrays in payload to grid and compact payload First, introduced a compact payload format that allows blocks of metrics to be dropped from the viewer->collector payload compressing 1200 bytes of LLSD into about 300, give-or-take. Then converted to using LLSD arrays in the payload to enumerate the regions encountered. This simplifies much data handling from the viewer all the way into the final formatter of the metrics on the grid. --- indra/newview/llappviewer.cpp | 2 +- indra/newview/lltexturefetch.cpp | 2 +- indra/newview/llviewerassetstats.cpp | 42 ++++++++++++------- indra/newview/llviewerassetstats.h | 10 ++++- indra/newview/tests/llviewerassetstats_test.cpp | 56 ++++++++++++------------- 5 files changed, 64 insertions(+), 48 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 3640d01642..32bd51d3e2 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3808,7 +3808,7 @@ void LLAppViewer::idle() // ViewerMetrics FPS piggy-backing on the debug timer. // The 5-second interval is nice for this purpose. If the object debug // bit moves or is disabled, please give this a suitable home. - LLViewerAssetStatsFF::record_fps_main(frame_rate_clamped); + LLViewerAssetStatsFF::record_fps_main(gFPSClamped); } } diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index e1f9d7bdcc..88905372f6 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -2915,7 +2915,7 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) // Merge existing stats into those from main, convert to LLSD main_stats.merge(*gViewerAssetStatsThread1); - LLSD merged_llsd = main_stats.asLLSD(); + LLSD merged_llsd = main_stats.asLLSD(true); // Add some additional meta fields to the content merged_llsd["session_id"] = mSessionID; diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index 399d62d2fc..5ad7725b3e 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llviewerassetstats.h" +#include "llregionhandle.h" #include "stdtypes.h" @@ -258,7 +259,7 @@ LLViewerAssetStats::recordFPS(F32 fps) } LLSD -LLViewerAssetStats::asLLSD() +LLViewerAssetStats::asLLSD(bool compact_output) { // Top-level tags static const LLSD::String tags[EVACCount] = @@ -290,7 +291,7 @@ LLViewerAssetStats::asLLSD() const duration_t now = LLViewerAssetStatsFF::get_timestamp(); mCurRegionStats->accumulateTime(now); - LLSD regions = LLSD::emptyMap(); + LLSD regions = LLSD::emptyArray(); for (PerRegionContainer::iterator it = mRegionStats.begin(); mRegionStats.end() != it; ++it) @@ -307,16 +308,25 @@ LLViewerAssetStats::asLLSD() for (int i = 0; i < LL_ARRAY_SIZE(tags); ++i) { - LLSD & slot = reg_stat[tags[i]]; - slot = LLSD::emptyMap(); - slot[enq_tag] = LLSD(S32(stats.mRequests[i].mEnqueued.getCount())); - slot[deq_tag] = LLSD(S32(stats.mRequests[i].mDequeued.getCount())); - slot[rcnt_tag] = LLSD(S32(stats.mRequests[i].mResponse.getCount())); - slot[rmin_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMin() * 1.0e-6)); - slot[rmax_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMax() * 1.0e-6)); - slot[rmean_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMean() * 1.0e-6)); + PerRegionStats::prs_group & group(stats.mRequests[i]); + + if ((! compact_output) || + group.mEnqueued.getCount() || + group.mDequeued.getCount() || + group.mResponse.getCount()) + { + LLSD & slot = reg_stat[tags[i]]; + slot = LLSD::emptyMap(); + slot[enq_tag] = LLSD(S32(stats.mRequests[i].mEnqueued.getCount())); + slot[deq_tag] = LLSD(S32(stats.mRequests[i].mDequeued.getCount())); + slot[rcnt_tag] = LLSD(S32(stats.mRequests[i].mResponse.getCount())); + slot[rmin_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMin() * 1.0e-6)); + slot[rmax_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMax() * 1.0e-6)); + slot[rmean_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMean() * 1.0e-6)); + } } + if ((! compact_output) || stats.mFPS.getCount()) { LLSD & slot = reg_stat["fps"]; slot = LLSD::emptyMap(); @@ -326,12 +336,12 @@ LLViewerAssetStats::asLLSD() slot[mean_tag] = LLSD(F64(stats.mFPS.getMean())); } - reg_stat["duration"] = LLSD::Real(stats.mTotalTime * 1.0e-6); - std::stringstream reg_handle; - reg_handle.width(16); - reg_handle.fill('0'); - reg_handle << std::hex << it->first; - regions[reg_handle.str()] = reg_stat; + U32 grid_x(0), grid_y(0); + grid_from_region_handle(it->first, &grid_x, &grid_y); + reg_stat["grid_x"] = LLSD::Integer(grid_x); + reg_stat["grid_y"] = LLSD::Integer(grid_y); + reg_stat["duration"] = LLSD::Real(stats.mTotalTime * 1.0e-6); + regions.append(reg_stat); } LLSD ret = LLSD::emptyMap(); diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index af6bf5b695..905ceefad5 100644 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -155,7 +155,7 @@ public: duration_t mStartTimestamp; LLSimpleStatMMM<> mFPS; - struct + struct prs_group { LLSimpleStatCounter mEnqueued; LLSimpleStatCounter mDequeued; @@ -232,7 +232,13 @@ public: // } // } // } - LLSD asLLSD(); + // + // @param compact_output If true, omits from conversion any mmm_block + // or stats_block that would contain all zero data. + // Useful for transmission when the receiver knows + // what is expected and will assume zero for missing + // blocks. + LLSD asLLSD(bool compact_output); protected: typedef std::map > PerRegionContainer; diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index 9c54266017..40a7103dba 100644 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -155,7 +155,7 @@ namespace tut ensure("Global gViewerAssetStatsMain should still be NULL", (NULL == gViewerAssetStatsMain)); - LLSD sd_full = it->asLLSD(); + LLSD sd_full = it->asLLSD(false); // Default (NULL) region ID doesn't produce LLSD results so should // get an empty map back from output @@ -163,7 +163,7 @@ namespace tut // Once the region is set, we will get a response even with no data collection it->setRegion(region1_handle); - sd_full = it->asLLSD(); + sd_full = it->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd_full, "duration", "regions")); ensure("Correct single-key LLSD map regions", is_single_key_map(sd_full["regions"], region1_handle_str)); @@ -204,7 +204,7 @@ namespace tut LLViewerAssetStats * it = new LLViewerAssetStats(); it->setRegion(region1_handle); - LLSD sd = it->asLLSD(); + LLSD sd = it->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region1_handle_str)); sd = sd[region1_handle_str]; @@ -229,7 +229,7 @@ namespace tut LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); - LLSD sd = gViewerAssetStatsMain->asLLSD(); + LLSD sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region1_handle_str)); sd = sd["regions"][region1_handle_str]; @@ -244,7 +244,7 @@ namespace tut // Reset and check zeros... // Reset leaves current region in place gViewerAssetStatsMain->reset(); - sd = gViewerAssetStatsMain->asLLSD()["regions"][region1_handle_str]; + sd = gViewerAssetStatsMain->asLLSD(false)["regions"][region1_handle_str]; delete gViewerAssetStatsMain; gViewerAssetStatsMain = NULL; @@ -267,9 +267,9 @@ namespace tut LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); - LLSD sd = gViewerAssetStatsThread1->asLLSD(); + LLSD sd = gViewerAssetStatsThread1->asLLSD(false); ensure("Other collector is empty", is_no_stats_map(sd)); - sd = gViewerAssetStatsMain->asLLSD(); + sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region1_handle_str)); sd = sd["regions"][region1_handle_str]; @@ -284,7 +284,7 @@ namespace tut // Reset and check zeros... // Reset leaves current region in place gViewerAssetStatsMain->reset(); - sd = gViewerAssetStatsMain->asLLSD()["regions"][region1_handle_str]; + sd = gViewerAssetStatsMain->asLLSD(false)["regions"][region1_handle_str]; delete gViewerAssetStatsMain; gViewerAssetStatsMain = NULL; @@ -316,7 +316,7 @@ namespace tut LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLSD sd = gViewerAssetStatsMain->asLLSD(); + LLSD sd = gViewerAssetStatsMain->asLLSD(false); // std::cout << sd << std::endl; @@ -340,7 +340,7 @@ namespace tut // Reset and check zeros... // Reset leaves current region in place gViewerAssetStatsMain->reset(); - sd = gViewerAssetStatsMain->asLLSD(); + sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region2_handle_str)); sd2 = sd["regions"][region2_handle_str]; @@ -388,7 +388,7 @@ namespace tut LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLSD sd = gViewerAssetStatsMain->asLLSD(); + LLSD sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions")); ensure("Correct double-key LLSD map regions", is_double_key_map(sd["regions"], region1_handle_str, region2_handle_str)); @@ -410,7 +410,7 @@ namespace tut // Reset and check zeros... // Reset leaves current region in place gViewerAssetStatsMain->reset(); - sd = gViewerAssetStatsMain->asLLSD(); + sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "duration", "regions")); ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region2_handle_str)); sd2 = sd["regions"][region2_handle_str]; @@ -453,9 +453,9 @@ namespace tut LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - LLSD sd = gViewerAssetStatsThread1->asLLSD(); + LLSD sd = gViewerAssetStatsThread1->asLLSD(false); ensure("Other collector is empty", is_no_stats_map(sd)); - sd = gViewerAssetStatsMain->asLLSD(); + sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region1_handle_str)); sd = sd["regions"][region1_handle_str]; @@ -473,7 +473,7 @@ namespace tut // Reset and check zeros... // Reset leaves current region in place gViewerAssetStatsMain->reset(); - sd = gViewerAssetStatsMain->asLLSD()["regions"][region1_handle_str]; + sd = gViewerAssetStatsMain->asLLSD(false)["regions"][region1_handle_str]; delete gViewerAssetStatsMain; gViewerAssetStatsMain = NULL; @@ -507,7 +507,7 @@ namespace tut s2.merge(s1); - LLSD s2_llsd = s2.asLLSD(); + LLSD s2_llsd = s2.asLLSD(false); ensure_equals("count after merge", 8, s2_llsd["regions"][region1_handle_str]["get_texture_temp_http"]["resp_count"].asInteger()); ensure_approximately_equals("min after merge", 2.0, s2_llsd["regions"][region1_handle_str]["get_texture_temp_http"]["resp_min"].asReal(), 22); @@ -562,8 +562,8 @@ namespace tut { s2.merge(s1); - LLSD src = s1.asLLSD(); - LLSD dst = s2.asLLSD(); + LLSD src = s1.asLLSD(false); + LLSD dst = s2.asLLSD(false); // Remove time stamps, they're a problem src.erase("duration"); @@ -621,8 +621,8 @@ namespace tut { s2.merge(s1); - LLSD src = s1.asLLSD(); - LLSD dst = s2.asLLSD(); + LLSD src = s1.asLLSD(false); + LLSD dst = s2.asLLSD(false); // Remove time stamps, they're a problem src.erase("duration"); @@ -689,8 +689,8 @@ namespace tut { s2.merge(s1); - LLSD src = s1.asLLSD(); - LLSD dst = s2.asLLSD(); + LLSD src = s1.asLLSD(false); + LLSD dst = s2.asLLSD(false); // Remove time stamps, they're a problem src.erase("duration"); @@ -745,8 +745,8 @@ namespace tut { s1.merge(s2); - LLSD src = s2.asLLSD(); - LLSD dst = s1.asLLSD(); + LLSD src = s2.asLLSD(false); + LLSD dst = s1.asLLSD(false); // Remove time stamps, they're a problem src.erase("duration"); @@ -804,8 +804,8 @@ namespace tut { s2.merge(s1); - LLSD src = s1.asLLSD(); - LLSD dst = s2.asLLSD(); + LLSD src = s1.asLLSD(false); + LLSD dst = s2.asLLSD(false); // Remove time stamps, they're a problem src.erase("duration"); @@ -859,8 +859,8 @@ namespace tut { s1.merge(s2); - LLSD src = s2.asLLSD(); - LLSD dst = s1.asLLSD(); + LLSD src = s2.asLLSD(false); + LLSD dst = s1.asLLSD(false); // Remove time stamps, they're a problem src.erase("duration"); -- cgit v1.2.3 From e0e223c196972e91da80b852921fe3ff627f8a68 Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Sat, 11 Dec 2010 14:37:00 -0800 Subject: Update unit tests to reflect the new array-of-regions style of LLSD serialization for viewer metrics. --- indra/newview/tests/llviewerassetstats_test.cpp | 268 +++++++++++++++++------- 1 file changed, 190 insertions(+), 78 deletions(-) diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index 40a7103dba..1bb4fb7c0c 100644 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -40,6 +40,7 @@ #include "../llviewerassetstats.h" #include "lluuid.h" #include "llsdutil.h" +#include "llregionhandle.h" static const char * all_keys[] = { @@ -92,10 +93,10 @@ static const char * mmm_sub_keys[] = static const LLUUID region1("4e2d81a3-6263-6ffe-ad5c-8ce04bee07e8"); static const LLUUID region2("68762cc8-b68b-4e45-854b-e830734f2d4a"); -static const U64 region1_handle(0x00000401000003f7ULL); -static const U64 region2_handle(0x000003f800000420ULL); -static const std::string region1_handle_str("00000401000003f7"); -static const std::string region2_handle_str("000003f800000420"); +static const U64 region1_handle(0x0000040000003f00ULL); +static const U64 region2_handle(0x0000030000004200ULL); +static const std::string region1_handle_str("0000040000003f00"); +static const std::string region2_handle_str("0000030000004200"); #if 0 static bool @@ -103,13 +104,13 @@ is_empty_map(const LLSD & sd) { return sd.isMap() && 0 == sd.size(); } -#endif static bool is_single_key_map(const LLSD & sd, const std::string & key) { return sd.isMap() && 1 == sd.size() && sd.has(key); } +#endif static bool is_double_key_map(const LLSD & sd, const std::string & key1, const std::string & key2) @@ -123,6 +124,73 @@ is_no_stats_map(const LLSD & sd) return is_double_key_map(sd, "duration", "regions"); } +static bool +is_single_slot_array(const LLSD & sd, U64 region_handle) +{ + U32 grid_x(0), grid_y(0); + grid_from_region_handle(region_handle, &grid_x, &grid_y); + + return (sd.isArray() && + 1 == sd.size() && + sd[0].has("grid_x") && + sd[0].has("grid_y") && + sd[0]["grid_x"].isInteger() && + sd[0]["grid_y"].isInteger() && + grid_x == sd[0]["grid_x"].asInteger() && + grid_y == sd[0]["grid_y"].asInteger()); +} + +static bool +is_double_slot_array(const LLSD & sd, U64 region_handle1, U64 region_handle2) +{ + U32 grid_x1(0), grid_y1(0); + U32 grid_x2(0), grid_y2(0); + grid_from_region_handle(region_handle1, &grid_x1, &grid_y1); + grid_from_region_handle(region_handle2, &grid_x2, &grid_y2); + + return (sd.isArray() && + 2 == sd.size() && + sd[0].has("grid_x") && + sd[0].has("grid_y") && + sd[0]["grid_x"].isInteger() && + sd[0]["grid_y"].isInteger() && + sd[1].has("grid_x") && + sd[1].has("grid_y") && + sd[1]["grid_x"].isInteger() && + sd[1]["grid_y"].isInteger() && + ((grid_x1 == sd[0]["grid_x"].asInteger() && + grid_y1 == sd[0]["grid_y"].asInteger() && + grid_x2 == sd[1]["grid_x"].asInteger() && + grid_y2 == sd[1]["grid_y"].asInteger()) || + (grid_x1 == sd[1]["grid_x"].asInteger() && + grid_y1 == sd[1]["grid_y"].asInteger() && + grid_x2 == sd[0]["grid_x"].asInteger() && + grid_y2 == sd[0]["grid_y"].asInteger()))); +} + +static LLSD +get_region(const LLSD & sd, U64 region_handle1) +{ + U32 grid_x(0), grid_y(0); + grid_from_region_handle(region_handle1, &grid_x, &grid_y); + + for (LLSD::array_const_iterator it(sd["regions"].beginArray()); + sd["regions"].endArray() != it; + ++it) + { + if ((*it).has("grid_x") && + (*it).has("grid_y") && + (*it)["grid_x"].isInteger() && + (*it)["grid_y"].isInteger() && + (*it)["grid_x"].asInteger() == grid_x && + (*it)["grid_y"].asInteger() == grid_y) + { + return *it; + } + } + return LLSD(); +} + namespace tut { struct tst_viewerassetstats_index @@ -165,9 +233,9 @@ namespace tut it->setRegion(region1_handle); sd_full = it->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd_full, "duration", "regions")); - ensure("Correct single-key LLSD map regions", is_single_key_map(sd_full["regions"], region1_handle_str)); + ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd_full["regions"], region1_handle)); - LLSD sd = sd_full["regions"][region1_handle_str]; + LLSD sd = sd_full["regions"][0]; delete it; @@ -206,8 +274,8 @@ namespace tut LLSD sd = it->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); - ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region1_handle_str)); - sd = sd[region1_handle_str]; + ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); + sd = sd[0]; delete it; @@ -231,8 +299,8 @@ namespace tut LLSD sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); - ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region1_handle_str)); - sd = sd["regions"][region1_handle_str]; + ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); + sd = sd["regions"][0]; // Check a few points on the tree for content ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); @@ -271,8 +339,8 @@ namespace tut ensure("Other collector is empty", is_no_stats_map(sd)); sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); - ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region1_handle_str)); - sd = sd["regions"][region1_handle_str]; + ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); + sd = sd["regions"][0]; // Check a few points on the tree for content ensure("sd[get_texture_non_temp_udp][enqueued] is 1", (1 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); @@ -284,7 +352,7 @@ namespace tut // Reset and check zeros... // Reset leaves current region in place gViewerAssetStatsMain->reset(); - sd = gViewerAssetStatsMain->asLLSD(false)["regions"][region1_handle_str]; + sd = gViewerAssetStatsMain->asLLSD(false)["regions"][0]; delete gViewerAssetStatsMain; gViewerAssetStatsMain = NULL; @@ -321,16 +389,18 @@ namespace tut // std::cout << sd << std::endl; ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions")); - ensure("Correct double-key LLSD map regions", is_double_key_map(sd["regions"], region1_handle_str, region2_handle_str)); - LLSD sd1 = sd["regions"][region1_handle_str]; - LLSD sd2 = sd["regions"][region2_handle_str]; + ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle)); + LLSD sd1 = get_region(sd, region1_handle); + LLSD sd2 = get_region(sd, region2_handle); + ensure("Region1 is present in results", sd1.isMap()); + ensure("Region2 is present in results", sd2.isMap()); // Check a few points on the tree for content - ensure("sd1[get_texture_non_temp_udp][enqueued] is 1", (1 == sd1["get_texture_non_temp_udp"]["enqueued"].asInteger())); - ensure("sd1[get_texture_temp_udp][enqueued] is 0", (0 == sd1["get_texture_temp_udp"]["enqueued"].asInteger())); - ensure("sd1[get_texture_non_temp_http][enqueued] is 0", (0 == sd1["get_texture_non_temp_http"]["enqueued"].asInteger())); - ensure("sd1[get_texture_temp_http][enqueued] is 0", (0 == sd1["get_texture_temp_http"]["enqueued"].asInteger())); - ensure("sd1[get_gesture_udp][dequeued] is 0", (0 == sd1["get_gesture_udp"]["dequeued"].asInteger())); + ensure_equals("sd1[get_texture_non_temp_udp][enqueued] is 1", sd1["get_texture_non_temp_udp"]["enqueued"].asInteger(), 1); + ensure_equals("sd1[get_texture_temp_udp][enqueued] is 0", sd1["get_texture_temp_udp"]["enqueued"].asInteger(), 0); + ensure_equals("sd1[get_texture_non_temp_http][enqueued] is 0", sd1["get_texture_non_temp_http"]["enqueued"].asInteger(), 0); + ensure_equals("sd1[get_texture_temp_http][enqueued] is 0", sd1["get_texture_temp_http"]["enqueued"].asInteger(), 0); + ensure_equals("sd1[get_gesture_udp][dequeued] is 0", sd1["get_gesture_udp"]["dequeued"].asInteger(), 0); // Check a few points on the tree for content ensure("sd2[get_gesture_udp][enqueued] is 4", (4 == sd2["get_gesture_udp"]["enqueued"].asInteger())); @@ -342,8 +412,8 @@ namespace tut gViewerAssetStatsMain->reset(); sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); - ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region2_handle_str)); - sd2 = sd["regions"][region2_handle_str]; + ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle)); + sd2 = sd["regions"][0]; delete gViewerAssetStatsMain; gViewerAssetStatsMain = NULL; @@ -391,9 +461,11 @@ namespace tut LLSD sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions")); - ensure("Correct double-key LLSD map regions", is_double_key_map(sd["regions"], region1_handle_str, region2_handle_str)); - LLSD sd1 = sd["regions"][region1_handle_str]; - LLSD sd2 = sd["regions"][region2_handle_str]; + ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle)); + LLSD sd1 = get_region(sd, region1_handle); + LLSD sd2 = get_region(sd, region2_handle); + ensure("Region1 is present in results", sd1.isMap()); + ensure("Region2 is present in results", sd2.isMap()); // Check a few points on the tree for content ensure("sd1[get_texture_non_temp_udp][enqueued] is 1", (1 == sd1["get_texture_non_temp_udp"]["enqueued"].asInteger())); @@ -412,14 +484,15 @@ namespace tut gViewerAssetStatsMain->reset(); sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "duration", "regions")); - ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region2_handle_str)); - sd2 = sd["regions"][region2_handle_str]; + ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle)); + sd2 = get_region(sd, region2_handle); + ensure("Region2 is present in results", sd2.isMap()); delete gViewerAssetStatsMain; gViewerAssetStatsMain = NULL; - ensure("sd2[get_texture_non_temp_udp][enqueued] is reset", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger())); - ensure("sd2[get_gesture_udp][enqueued] is reset", (0 == sd2["get_gesture_udp"]["enqueued"].asInteger())); + ensure_equals("sd2[get_texture_non_temp_udp][enqueued] is reset", sd2["get_texture_non_temp_udp"]["enqueued"].asInteger(), 0); + ensure_equals("sd2[get_gesture_udp][enqueued] is reset", sd2["get_gesture_udp"]["enqueued"].asInteger(), 0); } // Non-texture assets ignore transport and persistence flags @@ -457,8 +530,9 @@ namespace tut ensure("Other collector is empty", is_no_stats_map(sd)); sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); - ensure("Correct single-key LLSD map regions", is_single_key_map(sd["regions"], region1_handle_str)); - sd = sd["regions"][region1_handle_str]; + ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); + sd = get_region(sd, region1_handle); + ensure("Region1 is present in results", sd.isMap()); // Check a few points on the tree for content ensure("sd[get_gesture_udp][enqueued] is 0", (0 == sd["get_gesture_udp"]["enqueued"].asInteger())); @@ -473,15 +547,16 @@ namespace tut // Reset and check zeros... // Reset leaves current region in place gViewerAssetStatsMain->reset(); - sd = gViewerAssetStatsMain->asLLSD(false)["regions"][region1_handle_str]; + sd = get_region(gViewerAssetStatsMain->asLLSD(false), region1_handle); + ensure("Region1 is present in results", sd.isMap()); delete gViewerAssetStatsMain; gViewerAssetStatsMain = NULL; delete gViewerAssetStatsThread1; gViewerAssetStatsThread1 = NULL; - ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); - ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); + ensure_equals("sd[get_texture_non_temp_udp][enqueued] is reset", sd["get_texture_non_temp_udp"]["enqueued"].asInteger(), 0); + ensure_equals("sd[get_gesture_udp][dequeued] is reset", sd["get_gesture_udp"]["dequeued"].asInteger(), 0); } @@ -507,13 +582,13 @@ namespace tut s2.merge(s1); - LLSD s2_llsd = s2.asLLSD(false); + LLSD s2_llsd = get_region(s2.asLLSD(false), region1_handle); + ensure("Region1 is present in results", s2_llsd.isMap()); - ensure_equals("count after merge", 8, s2_llsd["regions"][region1_handle_str]["get_texture_temp_http"]["resp_count"].asInteger()); - ensure_approximately_equals("min after merge", 2.0, s2_llsd["regions"][region1_handle_str]["get_texture_temp_http"]["resp_min"].asReal(), 22); - ensure_approximately_equals("max after merge", 9.0, s2_llsd["regions"][region1_handle_str]["get_texture_temp_http"]["resp_max"].asReal(), 22); - ensure_approximately_equals("max after merge", 5.5, s2_llsd["regions"][region1_handle_str]["get_texture_temp_http"]["resp_mean"].asReal(), 22); - + ensure_equals("count after merge", s2_llsd["get_texture_temp_http"]["resp_count"].asInteger(), 8); + ensure_approximately_equals("min after merge", s2_llsd["get_texture_temp_http"]["resp_min"].asReal(), 2.0, 22); + ensure_approximately_equals("max after merge", s2_llsd["get_texture_temp_http"]["resp_max"].asReal(), 9.0, 22); + ensure_approximately_equals("max after merge", s2_llsd["get_texture_temp_http"]["resp_mean"].asReal(), 5.5, 22); } // LLViewerAssetStats::merge() basic functions work without corrupting source data @@ -565,17 +640,22 @@ namespace tut LLSD src = s1.asLLSD(false); LLSD dst = s2.asLLSD(false); + ensure_equals("merge src has single region", src["regions"].size(), 1); + ensure_equals("merge dst has dual regions", dst["regions"].size(), 2); + // Remove time stamps, they're a problem src.erase("duration"); - src["regions"][region1_handle_str].erase("duration"); + src["regions"][0].erase("duration"); dst.erase("duration"); - dst["regions"][region1_handle_str].erase("duration"); - dst["regions"][region2_handle_str].erase("duration"); + dst["regions"][0].erase("duration"); + dst["regions"][1].erase("duration"); - ensure_equals("merge src has single region", 1, src["regions"].size()); - ensure_equals("merge dst has dual regions", 2, dst["regions"].size()); - ensure("result from src is in dst", llsd_equals(src["regions"][region1_handle_str], - dst["regions"][region1_handle_str])); + LLSD s1_llsd = get_region(src, region1_handle); + ensure("Region1 is present in src", s1_llsd.isMap()); + LLSD s2_llsd = get_region(dst, region1_handle); + ensure("Region1 is present in dst", s2_llsd.isMap()); + + ensure("result from src is in dst", llsd_equals(s1_llsd, s2_llsd)); } s1.setRegion(region1_handle); @@ -624,23 +704,31 @@ namespace tut LLSD src = s1.asLLSD(false); LLSD dst = s2.asLLSD(false); + ensure_equals("merge src has single region (p2)", src["regions"].size(), 1); + ensure_equals("merge dst has single region (p2)", dst["regions"].size(), 1); + // Remove time stamps, they're a problem src.erase("duration"); - src["regions"][region1_handle_str].erase("duration"); + src["regions"][0].erase("duration"); dst.erase("duration"); - dst["regions"][region1_handle_str].erase("duration"); - - ensure_equals("src counts okay (enq)", 4, src["regions"][region1_handle_str]["get_other"]["enqueued"].asInteger()); - ensure_equals("src counts okay (deq)", 4, src["regions"][region1_handle_str]["get_other"]["dequeued"].asInteger()); - ensure_equals("src resp counts okay", 2, src["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); - ensure_approximately_equals("src respmin okay", 0.2829, src["regions"][region1_handle_str]["get_other"]["resp_min"].asReal(), 20); - ensure_approximately_equals("src respmax okay", 23.2892, src["regions"][region1_handle_str]["get_other"]["resp_max"].asReal(), 20); + dst["regions"][0].erase("duration"); + + LLSD s1_llsd = get_region(src, region1_handle); + ensure("Region1 is present in src", s1_llsd.isMap()); + LLSD s2_llsd = get_region(dst, region1_handle); + ensure("Region1 is present in dst", s2_llsd.isMap()); + + ensure_equals("src counts okay (enq)", s1_llsd["get_other"]["enqueued"].asInteger(), 4); + ensure_equals("src counts okay (deq)", s1_llsd["get_other"]["dequeued"].asInteger(), 4); + ensure_equals("src resp counts okay", s1_llsd["get_other"]["resp_count"].asInteger(), 2); + ensure_approximately_equals("src respmin okay", s1_llsd["get_other"]["resp_min"].asReal(), 0.2829, 20); + ensure_approximately_equals("src respmax okay", s1_llsd["get_other"]["resp_max"].asReal(), 23.2892, 20); - ensure_equals("dst counts okay (enq)", 12, dst["regions"][region1_handle_str]["get_other"]["enqueued"].asInteger()); - ensure_equals("src counts okay (deq)", 11, dst["regions"][region1_handle_str]["get_other"]["dequeued"].asInteger()); - ensure_equals("dst resp counts okay", 4, dst["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); - ensure_approximately_equals("dst respmin okay", 0.010, dst["regions"][region1_handle_str]["get_other"]["resp_min"].asReal(), 20); - ensure_approximately_equals("dst respmax okay", 23.2892, dst["regions"][region1_handle_str]["get_other"]["resp_max"].asReal(), 20); + ensure_equals("dst counts okay (enq)", s2_llsd["get_other"]["enqueued"].asInteger(), 12); + ensure_equals("src counts okay (deq)", s2_llsd["get_other"]["dequeued"].asInteger(), 11); + ensure_equals("dst resp counts okay", s2_llsd["get_other"]["resp_count"].asInteger(), 4); + ensure_approximately_equals("dst respmin okay", s2_llsd["get_other"]["resp_min"].asReal(), 0.010, 20); + ensure_approximately_equals("dst respmax okay", s2_llsd["get_other"]["resp_max"].asReal(), 23.2892, 20); } } @@ -692,16 +780,22 @@ namespace tut LLSD src = s1.asLLSD(false); LLSD dst = s2.asLLSD(false); + ensure_equals("merge src has single region", src["regions"].size(), 1); + ensure_equals("merge dst has single region", dst["regions"].size(), 1); + // Remove time stamps, they're a problem src.erase("duration"); - src["regions"][region1_handle_str].erase("duration"); + src["regions"][0].erase("duration"); dst.erase("duration"); - dst["regions"][region1_handle_str].erase("duration"); + dst["regions"][0].erase("duration"); - ensure_equals("dst counts come from src only", 3, dst["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); + LLSD s2_llsd = get_region(dst, region1_handle); + ensure("Region1 is present in dst", s2_llsd.isMap()); + + ensure_equals("dst counts come from src only", s2_llsd["get_other"]["resp_count"].asInteger(), 3); ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum", - dst["regions"][region1_handle_str]["get_other"]["resp_max"].asReal(), F64(0.0), 20); + s2_llsd["get_other"]["resp_max"].asReal(), F64(0.0), 20); } // Other way around @@ -748,16 +842,22 @@ namespace tut LLSD src = s2.asLLSD(false); LLSD dst = s1.asLLSD(false); + ensure_equals("merge src has single region", src["regions"].size(), 1); + ensure_equals("merge dst has single region", dst["regions"].size(), 1); + // Remove time stamps, they're a problem src.erase("duration"); - src["regions"][region1_handle_str].erase("duration"); + src["regions"][0].erase("duration"); dst.erase("duration"); - dst["regions"][region1_handle_str].erase("duration"); + dst["regions"][0].erase("duration"); - ensure_equals("dst counts come from src only (flipped)", 3, dst["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); + LLSD s2_llsd = get_region(dst, region1_handle); + ensure("Region1 is present in dst", s2_llsd.isMap()); + + ensure_equals("dst counts come from src only (flipped)", s2_llsd["get_other"]["resp_count"].asInteger(), 3); ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum (flipped)", - dst["regions"][region1_handle_str]["get_other"]["resp_max"].asReal(), F64(0.0), 20); + s2_llsd["get_other"]["resp_max"].asReal(), F64(0.0), 20); } } @@ -807,16 +907,22 @@ namespace tut LLSD src = s1.asLLSD(false); LLSD dst = s2.asLLSD(false); + ensure_equals("merge src has single region", src["regions"].size(), 1); + ensure_equals("merge dst has single region", dst["regions"].size(), 1); + // Remove time stamps, they're a problem src.erase("duration"); - src["regions"][region1_handle_str].erase("duration"); + src["regions"][0].erase("duration"); dst.erase("duration"); - dst["regions"][region1_handle_str].erase("duration"); + dst["regions"][0].erase("duration"); + + LLSD s2_llsd = get_region(dst, region1_handle); + ensure("Region1 is present in dst", s2_llsd.isMap()); - ensure_equals("dst counts come from src only", 3, dst["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); + ensure_equals("dst counts come from src only", s2_llsd["get_other"]["resp_count"].asInteger(), 3); ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum", - dst["regions"][region1_handle_str]["get_other"]["resp_min"].asReal(), F64(2.7), 20); + s2_llsd["get_other"]["resp_min"].asReal(), F64(2.7), 20); } // Other way around @@ -862,16 +968,22 @@ namespace tut LLSD src = s2.asLLSD(false); LLSD dst = s1.asLLSD(false); + ensure_equals("merge src has single region", src["regions"].size(), 1); + ensure_equals("merge dst has single region", dst["regions"].size(), 1); + // Remove time stamps, they're a problem src.erase("duration"); - src["regions"][region1_handle_str].erase("duration"); + src["regions"][0].erase("duration"); dst.erase("duration"); - dst["regions"][region1_handle_str].erase("duration"); + dst["regions"][0].erase("duration"); + + LLSD s2_llsd = get_region(dst, region1_handle); + ensure("Region1 is present in dst", s2_llsd.isMap()); - ensure_equals("dst counts come from src only (flipped)", 3, dst["regions"][region1_handle_str]["get_other"]["resp_count"].asInteger()); + ensure_equals("dst counts come from src only (flipped)", s2_llsd["get_other"]["resp_count"].asInteger(), 3); ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum (flipped)", - dst["regions"][region1_handle_str]["get_other"]["resp_min"].asReal(), F64(2.7), 20); + s2_llsd["get_other"]["resp_min"].asReal(), F64(2.7), 20); } } -- cgit v1.2.3 From 622c9f772c5ca11d2c05c78e23761fae2467dd2f Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Mon, 13 Dec 2010 11:17:41 -0500 Subject: Cleanup a cross-thread command dtor. It was technically correct but looked a bit dodgy with pointer ownership. --- indra/newview/lltexturefetch.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 88905372f6..e13fcf027f 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1844,8 +1844,9 @@ LLTextureFetch::~LLTextureFetch() while (! mCommands.empty()) { - delete mCommands.front(); + TFRequest * req(mCommands.front()); mCommands.erase(mCommands.begin()); + delete req; } // ~LLQueuedThread() called here -- cgit v1.2.3 From 62b9513353900079602bf29c3b8863697a50e46f Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Mon, 13 Dec 2010 12:37:34 -0800 Subject: permit flush when disabled. --- indra/llcommon/llevents.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 723cbd68c7..97e2bdeb57 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -515,7 +515,7 @@ bool LLEventQueue::post(const LLSD& event) void LLEventQueue::flush() { - if(!mEnabled || !mSignal) return; + if(!mSignal) return; // Consider the case when a given listener on this LLEventQueue posts yet // another event on the same queue. If we loop over mEventQueue directly, -- cgit v1.2.3 From 4bf715c512cf431dd2af7fc2d9256c1823b051d6 Mon Sep 17 00:00:00 2001 From: callum Date: Mon, 13 Dec 2010 14:21:30 -0800 Subject: SOCIAL-367 FIX HTTP Auth dialog does not indicate what server a user is entering a user name and password for in Webkit 4.7 --- indra/newview/llmediactrl.cpp | 8 ++++++++ indra/newview/skins/default/xui/en/notifications.xml | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 7fb75bd42a..69e0e12a36 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -1052,6 +1052,14 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) { LLNotification::Params auth_request_params; auth_request_params.name = "AuthRequest"; + + // pass in host name and realm for site (may be zero length but will always exist) + LLSD args; + LLURL raw_url( self->getAuthURL().c_str() ); + args["HOST_NAME"] = raw_url.getAuthority(); + args["REALM"] = self->getAuthRealm(); + + auth_request_params.substitutions = args; auth_request_params.payload = LLSD().with("media_id", mMediaTextureID); auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2, mMediaSource->getMediaPlugin()); LLNotifications::instance().add(auth_request_params); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 39d623b246..76f221f481 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6577,7 +6577,7 @@ Mute everyone? - Enter user name and password to continue. +The site at '<nolink>[HOST_NAME]</nolink>' in realm '[REALM]' requires a user name and password. -- cgit v1.2.3 From f32f26a1e17a5175863431db83edc2349568d588 Mon Sep 17 00:00:00 2001 From: callum Date: Mon, 13 Dec 2010 14:23:36 -0800 Subject: SOCIAL-364 FIX(2) Viewer Crash when selecting Browse Linden Homes button from side panel Changed default floater that opens if no parent found as per comments in task --- indra/newview/llmediactrl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 69e0e12a36..e916f3251e 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -1090,7 +1090,7 @@ void LLMediaCtrl::onPopup(const LLSD& notification, const LLSD& response) if (response["open"]) { // name of default floater to open - std::string floater_name = "web_content"; + std::string floater_name = "media_browser"; // look for parent floater name if ( gFloaterView ) -- cgit v1.2.3 From 5b5d2c428c90b5172d53e1fbc3eb6e27daffddcb Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 14 Dec 2010 09:54:28 -0800 Subject: Record update version in download marker so it can be recalled if resumed in another viewer session. --- .../updater/llupdatedownloader.cpp | 28 +++++++++++++++++----- .../viewer_components/updater/llupdatedownloader.h | 5 +++- .../viewer_components/updater/llupdaterservice.cpp | 5 ++-- .../updater/tests/llupdaterservice_test.cpp | 2 +- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/indra/viewer_components/updater/llupdatedownloader.cpp b/indra/viewer_components/updater/llupdatedownloader.cpp index 2dd0084fdc..f259e06476 100644 --- a/indra/viewer_components/updater/llupdatedownloader.cpp +++ b/indra/viewer_components/updater/llupdatedownloader.cpp @@ -48,7 +48,10 @@ public: Implementation(LLUpdateDownloader::Client & client); ~Implementation(); void cancel(void); - void download(LLURI const & uri, std::string const & hash, bool required); + void download(LLURI const & uri, + std::string const & hash, + std::string const & updateVersion, + bool required); bool isDownloading(void); size_t onHeader(void * header, size_t size); size_t onBody(void * header, size_t size); @@ -120,9 +123,12 @@ void LLUpdateDownloader::cancel(void) } -void LLUpdateDownloader::download(LLURI const & uri, std::string const & hash, bool required) +void LLUpdateDownloader::download(LLURI const & uri, + std::string const & hash, + std::string const & updateVersion, + bool required) { - mImplementation->download(uri, hash, required); + mImplementation->download(uri, hash, updateVersion, required); } @@ -208,13 +214,17 @@ void LLUpdateDownloader::Implementation::cancel(void) } -void LLUpdateDownloader::Implementation::download(LLURI const & uri, std::string const & hash, bool required) +void LLUpdateDownloader::Implementation::download(LLURI const & uri, + std::string const & hash, + std::string const & updateVersion, + bool required) { if(isDownloading()) mClient.downloadError("download in progress"); mDownloadRecordPath = downloadMarkerPath(); mDownloadData = LLSD(); mDownloadData["required"] = required; + mDownloadData["update_version"] = updateVersion; try { startDownloading(uri, hash); } catch(DownloadError const & e) { @@ -260,12 +270,18 @@ void LLUpdateDownloader::Implementation::resume(void) resumeDownloading(fileStatus.st_size); } else if(!validateDownload()) { LLFile::remove(filePath); - download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), mDownloadData["required"].asBoolean()); + download(LLURI(mDownloadData["url"].asString()), + mDownloadData["hash"].asString(), + mDownloadData["update_version"].asString(), + mDownloadData["required"].asBoolean()); } else { mClient.downloadComplete(mDownloadData); } } else { - download(LLURI(mDownloadData["url"].asString()), mDownloadData["hash"].asString(), mDownloadData["required"].asBoolean()); + download(LLURI(mDownloadData["url"].asString()), + mDownloadData["hash"].asString(), + mDownloadData["update_version"].asString(), + mDownloadData["required"].asBoolean()); } } catch(DownloadError & e) { mClient.downloadError(e.what()); diff --git a/indra/viewer_components/updater/llupdatedownloader.h b/indra/viewer_components/updater/llupdatedownloader.h index 4e20b307b8..0d635640cf 100644 --- a/indra/viewer_components/updater/llupdatedownloader.h +++ b/indra/viewer_components/updater/llupdatedownloader.h @@ -52,7 +52,10 @@ public: void cancel(void); // Start a new download. - void download(LLURI const & uri, std::string const & hash, bool required=false); + void download(LLURI const & uri, + std::string const & hash, + std::string const & updateVersion, + bool required=false); // Returns true if a download is in progress. bool isDownloading(void); diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 78f768facf..df1a963f81 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -339,6 +339,7 @@ bool LLUpdaterServiceImpl::checkForResume() if(download_info["current_version"].asString() == ll_get_version()) { mIsDownloading = true; + mNewVersion = download_info["update_version"].asString(); mUpdateDownloader.resume(); result = true; } @@ -370,7 +371,7 @@ void LLUpdaterServiceImpl::optionalUpdate(std::string const & newVersion, stopTimer(); mNewVersion = newVersion; mIsDownloading = true; - mUpdateDownloader.download(uri, hash, false); + mUpdateDownloader.download(uri, hash, newVersion, false); setState(LLUpdaterService::DOWNLOADING); } @@ -382,7 +383,7 @@ void LLUpdaterServiceImpl::requiredUpdate(std::string const & newVersion, stopTimer(); mNewVersion = newVersion; mIsDownloading = true; - mUpdateDownloader.download(uri, hash, true); + mUpdateDownloader.download(uri, hash, newVersion, true); setState(LLUpdaterService::DOWNLOADING); } diff --git a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp index fbdf9a4993..be5a5da50d 100644 --- a/indra/viewer_components/updater/tests/llupdaterservice_test.cpp +++ b/indra/viewer_components/updater/tests/llupdaterservice_test.cpp @@ -48,7 +48,7 @@ void LLUpdateChecker::check(std::string const & protocolVersion, std::string con std::string const & servicePath, std::string channel, std::string version) {} LLUpdateDownloader::LLUpdateDownloader(Client & ) {} -void LLUpdateDownloader::download(LLURI const & , std::string const &, bool){} +void LLUpdateDownloader::download(LLURI const & , std::string const &, std::string const &, bool){} class LLDir_Mock : public LLDir { -- cgit v1.2.3 From 126295523fe2ac9f8df47e9b3080cd9e6d389cc0 Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 14 Dec 2010 11:01:35 -0800 Subject: SOCIAL-365 FIX (via LLQtWebKit push) Text aliasing issue in Home side panel headings on Windows viewer --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index c0aba538ef..62bc0db80d 100644 --- a/install.xml +++ b/install.xml @@ -995,9 +995,9 @@ anguage Infrstructure (CLI) international standard windows md5sum - 4c45f2375016a36211ea4891357c321d + 5364a7ddd80f023022657844ef619f0e url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101203.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101214.tar.bz2
-- cgit v1.2.3 From 5dcf11ab4bf5903ff75513f037242cba1e3c11ca Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 14 Dec 2010 12:25:10 -0800 Subject: SOCIAL-373 FIX Media browser does not show https secure icon in address bar when a site is loaded over https --- indra/newview/llfloaterwebcontent.cpp | 17 +++++++++++++++++ indra/newview/llfloaterwebcontent.h | 2 ++ .../skins/default/xui/en/floater_web_content.xml | 13 ++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index d9748b2235..b4fa41e3f4 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llcombobox.h" +#include "lliconctrl.h" #include "llfloaterreg.h" #include "lllayoutstack.h" #include "llpluginclassmedia.h" @@ -63,6 +64,9 @@ BOOL LLFloaterWebContent::postBuild() getChildView("reload")->setEnabled( true ); getChildView("popexternal")->setEnabled( true ); + // cache image for secure browsing + mSecureLockIcon = getChild< LLIconCtrl >("media_secure_lock_flag"); + return TRUE; } @@ -248,6 +252,19 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent // we populate the status bar with URLs as they change so clear it now we're done const std::string end_str = ""; mStatusBarText->setText( end_str ); + + // decide if secure browsing icon should be displayed + std::string prefix = std::string("https://"); + std::string test_prefix = mCurrentURL.substr(0, prefix.length()); + LLStringUtil::toLower(test_prefix); + if(test_prefix == prefix) + { + mSecureLockIcon->setVisible(true); + } + else + { + mSecureLockIcon->setVisible(false); + } } else if(event == MEDIA_EVENT_CLOSE_REQUEST) { diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index 09b4945b65..4bd10342fa 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -34,6 +34,7 @@ class LLMediaCtrl; class LLComboBox; class LLTextBox; class LLProgressBar; +class LLIconCtrl; class LLFloaterWebContent : public LLFloater, @@ -69,6 +70,7 @@ private: LLMediaCtrl* mWebBrowser; LLComboBox* mAddressCombo; + LLIconCtrl *mSecureLockIcon; LLTextBox* mStatusBarText; LLProgressBar* mStatusBarProgress; std::string mCurrentURL; diff --git a/indra/newview/skins/default/xui/en/floater_web_content.xml b/indra/newview/skins/default/xui/en/floater_web_content.xml index 3072ca1b0e..46776d3f7e 100644 --- a/indra/newview/skins/default/xui/en/floater_web_content.xml +++ b/indra/newview/skins/default/xui/en/floater_web_content.xml @@ -114,6 +114,17 @@ + -- cgit v1.2.3 From b59dad36ba7b6d45c25f596e690df3150d94f1b4 Mon Sep 17 00:00:00 2001 From: Paul Guslisty Date: Sat, 18 Dec 2010 14:00:47 +0200 Subject: STORM-412 FIXED Resident profile controls aren't reshaped on changing panel width - Added parameters for text boxes to follow right side of panel --- .../newview/skins/default/xui/en/panel_my_profile.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/indra/newview/skins/default/xui/en/panel_my_profile.xml b/indra/newview/skins/default/xui/en/panel_my_profile.xml index 1b41f602cd..5b8abaca6f 100644 --- a/indra/newview/skins/default/xui/en/panel_my_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_my_profile.xml @@ -185,7 +185,7 @@ Date: Sat, 18 Dec 2010 18:35:32 +0200 Subject: STORM-796 ADDITIONAL_FIX Fixed Mac build. --- indra/llui/tests/llurlentry_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp index d0b2030d12..8f0a48018f 100644 --- a/indra/llui/tests/llurlentry_test.cpp +++ b/indra/llui/tests/llurlentry_test.cpp @@ -119,7 +119,7 @@ namespace tut S32 start = static_cast(result[0].first - text); S32 end = static_cast(result[0].second - text); std::string url = std::string(text+start, end-start); - label = entry.getLabel(url, dummyCallback); + label = entry.getLabel(url, boost::bind(dummyCallback, _1, _2, _3)); } ensure_equals(testname, label, expected); } -- cgit v1.2.3 From 1718ca48c22999986cd52acec71971bab486b490 Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Sat, 18 Dec 2010 20:17:36 +0200 Subject: STORM-511 FIXED Display tooltip for sender name on group notices. Changes: * Set tooltip for sender name. * Overridden handleTooltip() for the tooltip to be of normal (yellow) color. --- indra/newview/llinspecttoast.cpp | 11 +++++++++++ indra/newview/lltoastgroupnotifypanel.cpp | 1 + 2 files changed, 12 insertions(+) diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp index 58b3f0309f..d7b82667d1 100644 --- a/indra/newview/llinspecttoast.cpp +++ b/indra/newview/llinspecttoast.cpp @@ -46,6 +46,7 @@ public: virtual ~LLInspectToast(); /*virtual*/ void onOpen(const LLSD& notification_id); + /*virtual*/ BOOL handleToolTip(S32 x, S32 y, MASK mask); private: void onToastDestroy(LLToast * toast); @@ -73,6 +74,7 @@ LLInspectToast::~LLInspectToast() LLTransientFloaterMgr::getInstance()->removeControlView(this); } +// virtual void LLInspectToast::onOpen(const LLSD& notification_id) { LLInspect::onOpen(notification_id); @@ -103,6 +105,15 @@ void LLInspectToast::onOpen(const LLSD& notification_id) LLUI::positionViewNearMouse(this); } +// virtual +BOOL LLInspectToast::handleToolTip(S32 x, S32 y, MASK mask) +{ + // We don't like the way LLInspect handles tooltips + // (black tooltips look weird), + // so force using the default implementation (STORM-511). + return LLFloater::handleToolTip(x, y, mask); +} + void LLInspectToast::onToastDestroy(LLToast * toast) { closeFloater(false); diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp index 563c27c4d7..75178a6ef8 100644 --- a/indra/newview/lltoastgroupnotifypanel.cpp +++ b/indra/newview/lltoastgroupnotifypanel.cpp @@ -77,6 +77,7 @@ LLToastGroupNotifyPanel::LLToastGroupNotifyPanel(LLNotificationPtr& notification from << from_name << "/" << groupData.mName; LLTextBox* pTitleText = getChild("title"); pTitleText->setValue(from.str()); + pTitleText->setToolTip(from.str()); //message subject const std::string& subject = payload["subject"].asString(); -- cgit v1.2.3 From 2c68cb2c69348522ebb648aa4abd2ca7e4038b80 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Mon, 20 Dec 2010 10:38:36 -0800 Subject: fix windows build? --- indra/viewer_components/updater/llupdateinstaller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/viewer_components/updater/llupdateinstaller.cpp b/indra/viewer_components/updater/llupdateinstaller.cpp index d3347d330a..d450c068ad 100644 --- a/indra/viewer_components/updater/llupdateinstaller.cpp +++ b/indra/viewer_components/updater/llupdateinstaller.cpp @@ -25,7 +25,6 @@ #include "linden_common.h" #include -#include #include "llapr.h" #include "llprocesslauncher.h" #include "llupdateinstaller.h" @@ -35,6 +34,7 @@ #if defined(LL_WINDOWS) #pragma warning(disable: 4702) // disable 'unreachable code' so we can use lexical_cast (really!). #endif +#include namespace { -- cgit v1.2.3 From fdd5348f81d51363a1639de8b3cc4414fc0f4982 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Mon, 20 Dec 2010 11:34:06 -0800 Subject: Remove unimplemented software updater option. Fix potential double start of updater service. --- indra/newview/llviewercontrol.cpp | 3 ++- indra/newview/skins/default/xui/en/panel_preferences_setup.xml | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 2c75551285..8c5a52c187 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -506,7 +506,8 @@ void toggle_updater_service_active(LLControlVariable* control, const LLSD& new_v { if(new_value.asInteger()) { - LLUpdaterService().startChecking(); + LLUpdaterService update_service; + if(!update_service.isChecking()) update_service.startChecking(); } else { diff --git a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml index 542b6bcf6b..901a1257e0 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_setup.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml @@ -367,10 +367,12 @@ label="Install automatically" name="Install_automatically" value="3" /> + Date: Mon, 20 Dec 2010 12:02:56 -0800 Subject: Fix for a couple of minor merge issues. --- indra/newview/llfloaterwebcontent.cpp | 2 +- indra/newview/llmediactrl.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 14bd5baba1..51726112a0 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -312,7 +312,7 @@ void LLFloaterWebContent::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent else if(event == MEDIA_EVENT_PROGRESS_UPDATED ) { int percent = (int)self->getProgressPercent(); - mStatusBarProgress->setPercent( percent ); + mStatusBarProgress->setValue( percent ); } else if(event == MEDIA_EVENT_NAME_CHANGED ) { diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index f95592551c..38a74f90d3 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -62,6 +62,7 @@ public: Optional caret_color; Optional initial_mime_type; + Optional media_id; Params(); }; -- cgit v1.2.3 From d275251138932e8c6c10e4c5a0d05a003ffced90 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Mon, 20 Dec 2010 16:33:25 -0800 Subject: SOCIAL-399 FIX Viewer crash when canceling http auth on a media prim Reviewed by Callum at http://codereview.lindenlab.com/5636001 --- indra/llplugin/llpluginclassmedia.cpp | 4 ++-- indra/newview/llmediactrl.cpp | 2 +- indra/newview/llviewermedia.cpp | 24 ++++++++++++++++-------- indra/newview/llviewermedia.h | 2 +- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index e6c901dd5c..217b6e074d 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -682,7 +682,7 @@ void LLPluginClassMedia::sendPickFileResponse(const std::string &file) { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response"); message.setValue("file", file); - if(mPlugin->isBlocked()) + if(mPlugin && mPlugin->isBlocked()) { // If the plugin sent a blocking pick-file request, the response should unblock it. message.setValueBoolean("blocking_response", true); @@ -696,7 +696,7 @@ void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, message.setValueBoolean("ok", ok); message.setValue("username", username); message.setValue("password", password); - if(mPlugin->isBlocked()) + if(mPlugin && mPlugin->isBlocked()) { // If the plugin sent a blocking pick-file request, the response should unblock it. message.setValueBoolean("blocking_response", true); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 8d8f9dbebb..9493fddf50 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -1055,7 +1055,7 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) auth_request_params.substitutions = args; auth_request_params.payload = LLSD().with("media_id", mMediaTextureID); - auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2, mMediaSource->getMediaPlugin()); + auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2); LLNotifications::instance().add(auth_request_params); }; break; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index dacd663f83..60608a2c28 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1046,15 +1046,23 @@ bool LLViewerMedia::isParcelAudioPlaying() return (LLViewerMedia::hasParcelAudio() && gAudiop && LLAudioEngine::AUDIO_PLAYING == gAudiop->isInternetStreamPlaying()); } -void LLViewerMedia::onAuthSubmit(const LLSD& notification, const LLSD& response, LLPluginClassMedia* media) +void LLViewerMedia::onAuthSubmit(const LLSD& notification, const LLSD& response) { - if (response["ok"]) + LLViewerMediaImpl *impl = LLViewerMedia::getMediaImplFromTextureID(notification["payload"]["media_id"]); + if(impl) { - media->sendAuthResponse(true, response["username"], response["password"]); - } - else - { - media->sendAuthResponse(false, "", ""); + LLPluginClassMedia* media = impl->getMediaPlugin(); + if(media) + { + if (response["ok"]) + { + media->sendAuthResponse(true, response["username"], response["password"]); + } + else + { + media->sendAuthResponse(false, "", ""); + } + } } } @@ -3108,7 +3116,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla auth_request_params.substitutions = args; auth_request_params.payload = LLSD().with("media_id", mTextureId); - auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2, plugin); + auth_request_params.functor.function = boost::bind(&LLViewerMedia::onAuthSubmit, _1, _2); LLNotifications::instance().add(auth_request_params); }; break; diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 83fe790839..e2e342cc45 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -131,7 +131,7 @@ public: static bool isParcelMediaPlaying(); static bool isParcelAudioPlaying(); - static void onAuthSubmit(const LLSD& notification, const LLSD& response, LLPluginClassMedia* media); + static void onAuthSubmit(const LLSD& notification, const LLSD& response); // Clear all cookies for all plugins static void clearAllCookies(); -- cgit v1.2.3 From a8edb1af21a8c145e68935c30c1707ec8feb34b8 Mon Sep 17 00:00:00 2001 From: Merov Linden Date: Mon, 20 Dec 2010 23:09:16 -0800 Subject: STORM-151 : Fix llui_libtest integration test --- indra/integration_tests/llui_libtest/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt index 2a00dbee6f..e0772e55ca 100644 --- a/indra/integration_tests/llui_libtest/CMakeLists.txt +++ b/indra/integration_tests/llui_libtest/CMakeLists.txt @@ -10,6 +10,7 @@ include(00-Common) include(LLCommon) include(LLImage) include(LLImageJ2COJ) # ugh, needed for images +include(LLKDU) include(LLMath) include(LLMessage) include(LLRender) @@ -71,7 +72,10 @@ endif (DARWIN) target_link_libraries(llui_libtest llui llmessage + ${LLRENDER_LIBRARIES} ${LLIMAGE_LIBRARIES} + ${LLKDU_LIBRARIES} + ${KDU_LIBRARY} ${LLIMAGEJ2COJ_LIBRARIES} ${OS_LIBRARIES} ${GOOGLE_PERFTOOLS_LIBRARIES} -- cgit v1.2.3 From 5d6ccc5cdeb6e5314aa20f4f52359de57f6e8267 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Tue, 21 Dec 2010 16:38:06 -0800 Subject: SOCIAL-374 FIX Avatar images not loading on join.secondlife.com in Webkit 4.7 Reviewed by Callum --- indra/llplugin/llpluginclassmedia.cpp | 4 ++-- indra/llplugin/llpluginclassmedia.h | 2 +- indra/media_plugins/webkit/media_plugin_webkit.cpp | 8 +++---- indra/newview/app_settings/lindenlab.pem | 27 ++++++++++++++++++++++ indra/newview/llviewermedia.cpp | 4 ++-- 5 files changed, 36 insertions(+), 9 deletions(-) create mode 100644 indra/newview/app_settings/lindenlab.pem diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 217b6e074d..595c470a19 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -1236,9 +1236,9 @@ void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore) sendMessage(message); } -void LLPluginClassMedia::setCertificateFilePath(const std::string& path) +void LLPluginClassMedia::addCertificateFilePath(const std::string& path) { - LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "set_certificate_file_path"); + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path"); message.setValue("path", path); sendMessage(message); } diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index abc472f501..c826e13c40 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -203,7 +203,7 @@ public: void proxyWindowOpened(const std::string &target, const std::string &uuid); void proxyWindowClosed(const std::string &uuid); void ignore_ssl_cert_errors(bool ignore); - void setCertificateFilePath(const std::string& path); + void addCertificateFilePath(const std::string& path); // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE std::string getNavigateURI() const { return mNavigateURI; }; diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 19244d2d1f..d6f8ae3e16 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -1247,12 +1247,12 @@ void MediaPluginWebKit::receiveMessage(const char *message_string) llwarns << "Ignoring ignore_ssl_cert_errors message (llqtwebkit version is too old)." << llendl; #endif } - else if(message_name == "set_certificate_file_path") + else if(message_name == "add_certificate_file_path") { -#if LLQTWEBKIT_API_VERSION >= 3 - LLQtWebKit::getInstance()->setCAFile( message_in.getValue("path") ); +#if LLQTWEBKIT_API_VERSION >= 6 + LLQtWebKit::getInstance()->addCAFile( message_in.getValue("path") ); #else - llwarns << "Ignoring set_certificate_file_path message (llqtwebkit version is too old)." << llendl; + llwarns << "Ignoring add_certificate_file_path message (llqtwebkit version is too old)." << llendl; #endif } else if(message_name == "init_history") diff --git a/indra/newview/app_settings/lindenlab.pem b/indra/newview/app_settings/lindenlab.pem new file mode 100644 index 0000000000..cf88d0e047 --- /dev/null +++ b/indra/newview/app_settings/lindenlab.pem @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE----- +MIIEUDCCA7mgAwIBAgIJAN4ppNGwj6yIMA0GCSqGSIb3DQEBBAUAMIHMMQswCQYD +VQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZyYW5j +aXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5jLjEpMCcGA1UECxMgTGluZGVu +IExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAnBgNVBAMTIExpbmRlbiBMYWIg +Q2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZIhvcNAQkBFhBjYUBsaW5kZW5s +YWIuY29tMB4XDTA1MDQyMTAyNDAzMVoXDTI1MDQxNjAyNDAzMVowgcwxCzAJBgNV +BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRnJhbmNp +c2NvMRkwFwYDVQQKExBMaW5kZW4gTGFiLCBJbmMuMSkwJwYDVQQLEyBMaW5kZW4g +TGFiIENlcnRpZmljYXRlIEF1dGhvcml0eTEpMCcGA1UEAxMgTGluZGVuIExhYiBD +ZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgkqhkiG9w0BCQEWEGNhQGxpbmRlbmxh +Yi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKXh1MThucdTbMg9bYBO +rAm8yWns32YojB0PRfbq8rUjepEhTm3/13s0u399Uc202v4ejcGhkIDWJZd2NZMF +oKrhmRfxGHSKPCuFaXC3jh0lRECj7k8FoPkcmaPjSyodrDFDUUuv+C06oYJoI+rk +8REyal9NwgHvqCzOrZtiTXAdAgMBAAGjggE2MIIBMjAdBgNVHQ4EFgQUO1zK2e1f +1wO1fHAjq6DTJobKDrcwggEBBgNVHSMEgfkwgfaAFDtcytntX9cDtXxwI6ug0yaG +yg63oYHSpIHPMIHMMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEW +MBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEZMBcGA1UEChMQTGluZGVuIExhYiwgSW5j +LjEpMCcGA1UECxMgTGluZGVuIExhYiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxKTAn +BgNVBAMTIExpbmRlbiBMYWIgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYJKoZI +hvcNAQkBFhBjYUBsaW5kZW5sYWIuY29tggkA3imk0bCPrIgwDAYDVR0TBAUwAwEB +/zANBgkqhkiG9w0BAQQFAAOBgQA/ZkgfvwHYqk1UIAKZS3kMCxz0HvYuEQtviwnu +xA39CIJ65Zozs28Eg1aV9/Y+Of7TnWhW+U3J3/wD/GghaAGiKK6vMn9gJBIdBX/9 +e6ef37VGyiOEFFjnUIbuk0RWty0orN76q/lI/xjCi15XSA/VSq2j4vmnwfZcPTDu +glmQ1A== +-----END CERTIFICATE----- + diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 60608a2c28..d3b6dcd86f 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -1829,7 +1829,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) } // start by assuming the default CA file will be used - std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "CA.pem" ); + std::string ca_path = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "lindenlab.pem" ); // default turned off so pick up the user specified path if( ! gSavedSettings.getBOOL("BrowserUseDefaultCAFile")) @@ -1837,7 +1837,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type) ca_path = gSavedSettings.getString("BrowserCAFilePath"); } // set the path to the CA.pem file - media_source->setCertificateFilePath( ca_path ); + media_source->addCertificateFilePath( ca_path ); media_source->proxy_setup(gSavedSettings.getBOOL("BrowserProxyEnabled"), gSavedSettings.getString("BrowserProxyAddress"), gSavedSettings.getS32("BrowserProxyPort")); -- cgit v1.2.3 From ec3a58d2e3ab3bfbab46aa699b0e978e9859bf6d Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Tue, 21 Dec 2010 16:46:30 -0800 Subject: SOCIAL-374 FIX Avatar images not loading on join.secondlife.com in Webkit 4.7 Updated llqtwebkit build for Mac from changeset f8e31d21585d in the llqtwebkit repository. --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index 0166abcfb8..b4acef4e8c 100644 --- a/install.xml +++ b/install.xml @@ -981,9 +981,9 @@ anguage Infrstructure (CLI) international standard darwin md5sum - d7bd19331996264c1b2b944575fc63f8 + 66c46841825ab4969ec875b5c8f9b24c url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-darwin-qt4.7.1-20101215.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-darwin-qt4.7.1-20101221.tar.bz2 linux -- cgit v1.2.3 From 6182ded4e9b4ba076add7a840c535589d36ec283 Mon Sep 17 00:00:00 2001 From: callum Date: Tue, 21 Dec 2010 17:11:01 -0800 Subject: SOCIAL-374 FIX (Windows) Avatar images not loading on join.secondlife.com in Webkit 4.7 Updated llqtwebkit build for Windows from changeset f8e31d21585d in the llqtwebkit repository. --- install.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install.xml b/install.xml index b4acef4e8c..cc1f1f5c71 100644 --- a/install.xml +++ b/install.xml @@ -995,9 +995,9 @@ anguage Infrstructure (CLI) international standard windows md5sum - 3e071fbdd8ac671478098af3461145ec + b678c4d18ea8e4fab42b20f8d0b2629a url - http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101214b.tar.bz2 + http://viewer-source-downloads.s3.amazonaws.com/install_pkgs/llqtwebkit-windows-qt4.7.1-20101221.tar.bz2 -- cgit v1.2.3