From f8eaee753174d0cab4e4edcf795f422706d6f302 Mon Sep 17 00:00:00 2001
From: Richard Linden <none@none>
Date: Fri, 2 Nov 2012 20:03:44 -0700
Subject: [PATCH] SH-3499  Ensure asset stats output is correct improvements to
 predicate API default rules encapsulated in LLInitParam removed empty flag
 from viewer asset stats

---
 indra/llcommon/llinitparam.cpp       |  10 ++
 indra/llcommon/llinitparam.h         |  25 ++-
 indra/llcommon/llpredicate.h         |  80 +++++----
 indra/llcommon/llsdparam.cpp         |   4 +-
 indra/llcommon/llsdparam.h           |  19 +-
 indra/llui/llfloater.cpp             |   5 +-
 indra/llui/llpanel.cpp               |   4 +-
 indra/llui/lluictrlfactory.h         |   4 +-
 indra/llui/llxuiparser.cpp           |   2 +-
 indra/llui/llxuiparser.h             |  18 +-
 indra/newview/llviewerassetstats.cpp | 254 +++++++++++++--------------
 indra/newview/llviewerassetstats.h   |   1 -
 12 files changed, 251 insertions(+), 175 deletions(-)

diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp
index 53254c3b566..d20fc032277 100644
--- a/indra/llcommon/llinitparam.cpp
+++ b/indra/llcommon/llinitparam.cpp
@@ -32,6 +32,12 @@
 
 namespace LLInitParam
 {
+
+	predicate_rule_t default_parse_rules() 
+	{ 
+		return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY) && !ll_make_predicate(HAS_DEFAULT_VALUE); 
+	}
+
 	//
 	// Param
 	//
@@ -247,6 +253,10 @@ namespace LLInitParam
 			}
 		}
 
+		if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
+		{
+			serialized |= parser.writeValue(Flag(), name_stack);
+		}
 		// was anything serialized in this block?
 		return serialized;
 	}
diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h
index c82b1226ee4..6177cc7d12b 100644
--- a/indra/llcommon/llinitparam.h
+++ b/indra/llcommon/llinitparam.h
@@ -297,11 +297,13 @@ namespace LLInitParam
 		PROVIDED,
 		REQUIRED,
 		VALID,
-		NON_DEFAULT
+		HAS_DEFAULT_VALUE,
+		EMPTY
 	};
 
 	typedef LLPredicate::Rule<ESerializePredicates> predicate_rule_t;
 
+	predicate_rule_t default_parse_rules();
 
 	// various callbacks and constraints associated with an individual param
 	struct LL_COMMON_API ParamDescriptor
@@ -912,7 +914,10 @@ namespace LLInitParam
 			const self_t* diff_typed_param = static_cast<const self_t*>(diff_param);
 
 			LLPredicate::Value<ESerializePredicates> predicate;
-			predicate.set(NON_DEFAULT, !diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()));
+			if (diff_typed_param && ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue()))
+			{
+				predicate.set(HAS_DEFAULT_VALUE);
+			}
 
 			if (typed_param.isValid())
 			{
@@ -925,6 +930,8 @@ namespace LLInitParam
 				predicate.set(PROVIDED, false);
 			}
 
+			predicate.set(EMPTY, false);
+
 			if (!predicate_rule.check(predicate)) return false;
 
 			if (!name_stack.empty())
@@ -1285,6 +1292,8 @@ namespace LLInitParam
 				predicate.set(PROVIDED, false);
 			}			
 
+			predicate.set(EMPTY, typed_param.mValues.empty());
+
 			if (!predicate_rule.check(predicate)) return false;
 
 			for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end();
@@ -1325,6 +1334,12 @@ namespace LLInitParam
 
 				name_stack.pop_back();
 			}
+
+			if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
+			{
+				serialized |= parser.writeValue(Flag(), name_stack);
+			}
+
 			return serialized;
 		}
 
@@ -1567,6 +1582,12 @@ namespace LLInitParam
 
 				name_stack.pop_back();
 			}
+
+			if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY)))
+			{
+				serialized |= parser.writeValue(Flag(), name_stack);
+			}
+
 			return serialized;
 		}
 
diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h
index 3f7abe67f17..6c9e5fc145b 100644
--- a/indra/llcommon/llpredicate.h
+++ b/indra/llcommon/llpredicate.h
@@ -73,43 +73,37 @@ namespace LLPredicate
 			return new_value;
 		}
 
-		void set(ENUM e, bool value)
+		void set(ENUM e, bool value = true)
 		{
 			llassert(0 <= e && e < cMaxEnum);
-			modifyPredicate(0x1 << (S32)e, cPredicateFlagsFromEnum[e], value);
+			mPredicateFlags = modifyPredicate(0x1 << (S32)e, cPredicateFlagsFromEnum[e], value, mPredicateFlags);
 		}
 
 		void set(const Value other, bool value)
 		{
-			U32 predicate_flags = other.mPredicateFlags;
-			while(predicate_flags)
+			predicate_flag_t predicate_flags_to_set = other.mPredicateFlags;
+			predicate_flag_t cumulative_flags = 0;
+			while(predicate_flags_to_set)
 			{
-				U32 next_flags = clearLSB(predicate_flags);
-				lsb_flag = predicate_flags ^ next_flags;
+				predicate_flag_t next_flags = clearLSB(predicate_flags_to_set);
+				predicate_flag_t lsb_flag = predicate_flags_to_set ^ next_flags;
 
-				U32 mask = 0;
+				predicate_flag_t mask = 0;
+				predicate_flag_t cur_flags = mPredicateFlags;
 				for (S32 i = 0; i < cMaxEnum; i++)
 				{
 					if (cPredicateFlagsFromEnum[i] & lsb_flag)
 					{
 						mask |= cPredicateFlagsFromEnum[i];
-						modifyPredicate(0x1 << (0x1 << i ), cPredicateFlagsFromEnum[i], !value);
+						cur_flags = modifyPredicate(0x1 << (0x1 << i ), cPredicateFlagsFromEnum[i], !value, cur_flags);
 					}
 				}
 
-				modifyPredicate(lsb_flag, mask, value);
+				cumulative_flags |= modifyPredicate(lsb_flag, mask, value, cur_flags);
 				
-				predicate_flags = next_flags;
-			} 
-		}
-
-		void forget(ENUM e)
-		{
-			set(e, true);
-			U32 flags_with_predicate = mPredicateFlags;
-			set(e, false);
-			// ambiguous value is result of adding and removing predicate at the same time!
-			mPredicateFlags |= flags_with_predicate;
+				predicate_flags_to_set = next_flags;
+			}
+			mPredicateFlags = cumulative_flags;
 		}
 
 		void forget(const Value value)
@@ -131,6 +125,11 @@ namespace LLPredicate
 			return mPredicateFlags == 0;
 		}
 
+		bool someSet() const
+		{
+			return mPredicateFlags != 0;
+		}
+
 	private:
 
 		predicate_flag_t clearLSB(predicate_flag_t value)
@@ -138,16 +137,16 @@ namespace LLPredicate
 			return value & (value - 1);
 		}
 
-		void modifyPredicate(predicate_flag_t predicate_flag, predicate_flag_t mask, bool value)
+		predicate_flag_t modifyPredicate(predicate_flag_t predicate_flag, predicate_flag_t mask, predicate_flag_t value, bool set)
 		{
 			llassert(clearLSB(predicate_flag) == 0);
 			predicate_flag_t flags_to_modify;
 
-			if (value)
+			if (set)
 			{
 				flags_to_modify = (mPredicateFlags & ~mask);
 				// clear flags not containing predicate to be added
-				mPredicateFlags &= mask;
+				value &= mask;
 				// shift flags, in effect adding predicate
 				flags_to_modify *= predicate_flag;
 			}
@@ -155,12 +154,13 @@ namespace LLPredicate
 			{
 				flags_to_modify = mPredicateFlags & mask;
 				// clear flags containing predicate to be removed
-				mPredicateFlags &= ~mask;
+				value &= ~mask;
 				// shift flags, in effect removing predicate
 				flags_to_modify /= predicate_flag;
 			}
 			// put modified flags back
-			mPredicateFlags |= flags_to_modify;
+			value |= flags_to_modify;
+			return value;
 		}
 
 		predicate_flag_t mPredicateFlags;
@@ -174,10 +174,6 @@ namespace LLPredicate
 		:	mRule(value)
 		{}
 
-		Rule(const Rule& other)
-		:	mRule(other.mRule)
-		{}
-
 		Rule(const Value<ENUM> other)
 		:	mRule(other)
 		{}
@@ -185,17 +181,37 @@ namespace LLPredicate
 		Rule()
 		{}
 
+		void require(const Value<ENUM> value)
+		{
+			mRule.set(value, require);
+		}
+
+		void allow(const Value<ENUM> value)
+		{
+			mRule.forget(value);
+		}
+
 		bool check(const Value<ENUM> value) const
 		{
-			return !(mRule && value).noneSet();
+			return (mRule && value).someSet();
+		}
+
+		bool requires(const Value<ENUM> value) const
+		{
+			return (mRule && value).someSet() && (!mRule && value).noneSet();
+		}
+
+		bool isAmbivalent(const Value<ENUM> value) const
+		{
+			return (mRule && value).someSet() && (!mRule && value).someSet();
 		}
 
-		bool isTriviallyTrue() const
+		bool acceptsAll() const
 		{
 			return mRule.allSet();
 		}
 
-		bool isTriviallyFalse() const
+		bool acceptsNone() const
 		{
 			return mRule.noneSet();
 		}
diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp
index c10e1b1e20e..345e30f4b46 100644
--- a/indra/llcommon/llsdparam.cpp
+++ b/indra/llcommon/llsdparam.cpp
@@ -102,13 +102,13 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool
 	//readSDValues(sd, block);
 }
 
-void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block, LLInitParam::predicate_rule_t rules)
+void LLParamSDParser::writeSDImpl(LLSD& sd, const LLInitParam::BaseBlock& block, const LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block)
 {
 	mNameStack.clear();
 	mWriteRootSD = &sd;
 
 	name_stack_t name_stack;
-	block.serializeBlock(*this, name_stack, rules);
+	block.serializeBlock(*this, name_stack, rules, diff_block);
 }
 
 /*virtual*/ std::string LLParamSDParser::getCurrentElementName()
diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h
index 032e506fd84..1181c2d4339 100644
--- a/indra/llcommon/llsdparam.h
+++ b/indra/llcommon/llsdparam.h
@@ -50,11 +50,28 @@ typedef LLInitParam::Parser parser_t;
 public:
 	LLParamSDParser();
 	void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false);
-	void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block, LLInitParam::predicate_rule_t rules = LLInitParam::predicate_rule_t(LLInitParam::PROVIDED) && LLInitParam::NON_DEFAULT);
+	template<typename BLOCK>
+	void writeSD(LLSD& sd, 
+		const BLOCK& block, 
+		const LLInitParam::predicate_rule_t rules = LLInitParam::default_parse_rules(),
+		const LLInitParam::BaseBlock* diff_block = NULL)
+	{
+		if (!diff_block 
+			&& !rules.isAmbivalent(LLInitParam::HAS_DEFAULT_VALUE))
+		{
+			diff_block = &LLInitParam::defaultValue<BLOCK>();
+		}
+		writeSDImpl(sd, block, rules, diff_block);
+	}
 
 	/*virtual*/ std::string getCurrentElementName();
 
 private:
+	void writeSDImpl(LLSD& sd, 
+		const LLInitParam::BaseBlock& block, 
+		const LLInitParam::predicate_rule_t,
+		const LLInitParam::BaseBlock* diff_block);
+
 	void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack);
 
 	template<typename T>
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index c4a5d1f05eb..34556b8aeb0 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -3085,7 +3085,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str
 			parser.readXUI(node, output_params, LLUICtrlFactory::getInstance()->getCurFileName());
 			setupParamsForExport(output_params, parent);
 			output_node->setName(node->getName()->mString);
-			parser.writeXUI(output_node, output_params, LLInitParam::predicate_rule_t(LLInitParam::PROVIDED) && LLInitParam::NON_DEFAULT, &default_params);
+			parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
 			return TRUE;
 		}
 
@@ -3115,9 +3115,8 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str
 	{
 		Params output_params(params);
 		setupParamsForExport(output_params, parent);
-        Params default_params(LLUICtrlFactory::getDefaultParams<LLFloater>());
 		output_node->setName(node->getName()->mString);
-		parser.writeXUI(output_node, output_params, LLInitParam::predicate_rule_t(LLInitParam::PROVIDED) && LLInitParam::NON_DEFAULT, &default_params);
+		parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
 	}
 
 	// Default floater position to top-left corner of screen
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index f3d6687e408..a5ffcc8ec75 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -520,7 +520,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
 				Params output_params(params);
 				setupParamsForExport(output_params, parent);
 				output_node->setName(node->getName()->mString);
-				parser.writeXUI(output_node, output_params, LLInitParam::predicate_rule_t(LLInitParam::PROVIDED) && LLInitParam::NON_DEFAULT, &default_params);
+				parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
 				return TRUE;
 			}
 		
@@ -551,7 +551,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
 			Params output_params(params);
 			setupParamsForExport(output_params, parent);
 			output_node->setName(node->getName()->mString);
-			parser.writeXUI(output_node, output_params, LLInitParam::predicate_rule_t(LLInitParam::PROVIDED) && LLInitParam::NON_DEFAULT, &default_params);
+			parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params);
 		}
 		
 		params.from_xui = true;
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 6513f97ca01..b53b71f6905 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -270,10 +270,8 @@ class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
 			// We always want to output top-left coordinates
 			typename T::Params output_params(params);
 			T::setupParamsForExport(output_params, parent);
-			// Export only the differences between this any default params
-			typename T::Params default_params(getDefaultParams<T>());
 			copyName(node, output_node);
-			parser.writeXUI(output_node, output_params, LLInitParam::predicate_rule_t(LLInitParam::PROVIDED) && LLInitParam::NON_DEFAULT, &default_params);
+			parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &getDefaultParams<T>());
 		}
 
 		// Apply layout transformations, usually munging rect
diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp
index 6fc32dbf9c4..0c91390bc15 100644
--- a/indra/llui/llxuiparser.cpp
+++ b/indra/llui/llxuiparser.cpp
@@ -861,7 +861,7 @@ bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& blo
 	return any_parsed;
 }
 
-void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block)
+void LLXUIParser::writeXUIImpl(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block)
 {
 	mWriteRootNode = node;
 	name_stack_t name_stack = Parser::name_stack_t();
diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h
index 9b6b2a321b2..8d0276a8ad4 100644
--- a/indra/llui/llxuiparser.h
+++ b/indra/llui/llxuiparser.h
@@ -109,9 +109,25 @@ LOG_CLASS(LLXUIParser);
 	/*virtual*/ void parserError(const std::string& message);
 
 	void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename = LLStringUtil::null, bool silent=false);
-	void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, LLInitParam::predicate_rule_t rules = LLInitParam::predicate_rule_t(LLInitParam::PROVIDED) && LLInitParam::NON_DEFAULT, const LLInitParam::BaseBlock* diff_block = NULL);
+	template<typename BLOCK>
+	void writeXUI(LLXMLNodePtr node, 
+				const BLOCK& block, 
+				const LLInitParam::predicate_rule_t rules = LLInitParam::default_parse_rules(),
+				const LLInitParam::BaseBlock* diff_block = NULL)
+	{
+		if (!diff_block 
+			&& !rules.isAmbivalent(LLInitParam::HAS_DEFAULT_VALUE))
+		{
+			diff_block = &LLInitParam::defaultValue<BLOCK>();
+		}
+		writeXUIImpl(node, block, rules, diff_block);
+	}
 
 private:
+	void writeXUIImpl(LLXMLNodePtr node, 
+		const LLInitParam::BaseBlock& block, 
+		const LLInitParam::predicate_rule_t rules, 
+		const LLInitParam::BaseBlock* diff_block);
 	bool readXUIImpl(LLXMLNodePtr node, LLInitParam::BaseBlock& block);
 	bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block);
 
diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp
index e4f64f30760..df43c4b3445 100755
--- a/indra/newview/llviewerassetstats.cpp
+++ b/indra/newview/llviewerassetstats.cpp
@@ -303,138 +303,133 @@ void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output)
 		mCurRecording->update();
 	}
 	
-	if (mRegionRecordings.empty())
-	{
-		stats.regions.add().empty.setProvided();
-	}
-	else
+	stats.regions.setProvided();
+	
+	for (PerRegionRecordingContainer::iterator it = mRegionRecordings.begin(), end_it = mRegionRecordings.end();
+		it != end_it;
+		++it)
 	{
-		for (PerRegionRecordingContainer::iterator it = mRegionRecordings.begin(), end_it = mRegionRecordings.end();
-			it != end_it;
-			++it)
+		RegionStats& r = stats.regions.add();
+		LLTrace::Recording& rec = it->second;
+		if (!compact_output
+			|| rec.getSum(sEnqueued[EVACTextureTempHTTPGet]) 
+			|| rec.getSum(sDequeued[EVACTextureTempHTTPGet])
+			|| rec.getSum(sResponse[EVACTextureTempHTTPGet]).value())
 		{
-			RegionStats& r = stats.regions.add();
-			LLTrace::Recording& rec = it->second;
-			if (!compact_output
-				|| rec.getSum(sEnqueued[EVACTextureTempHTTPGet]) 
-				|| rec.getSum(sDequeued[EVACTextureTempHTTPGet])
-				|| rec.getSum(sResponse[EVACTextureTempHTTPGet]).value())
-			{
-				r.get_texture_temp_http	.enqueued(rec.getSum(sEnqueued[EVACTextureTempHTTPGet]))
-										.dequeued(rec.getSum(sDequeued[EVACTextureTempHTTPGet]))
-										.resp_count(rec.getSum(sResponse[EVACTextureTempHTTPGet]).value())
-										.resp_min(rec.getMin(sResponse[EVACTextureTempHTTPGet]).value())
-										.resp_max(rec.getMax(sResponse[EVACTextureTempHTTPGet]).value())
-										.resp_mean(rec.getMean(sResponse[EVACTextureTempHTTPGet]).value());
-			}
-			if (!compact_output
-				|| rec.getSum(sEnqueued[EVACTextureTempUDPGet]) 
-				|| rec.getSum(sDequeued[EVACTextureTempUDPGet])
-				|| rec.getSum(sResponse[EVACTextureTempUDPGet]).value())
-			{
-				r.get_texture_temp_udp	.enqueued(rec.getSum(sEnqueued[EVACTextureTempUDPGet]))
-										.dequeued(rec.getSum(sDequeued[EVACTextureTempUDPGet]))
-										.resp_count(rec.getSum(sResponse[EVACTextureTempUDPGet]).value())
-										.resp_min(rec.getMin(sResponse[EVACTextureTempUDPGet]).value())
-										.resp_max(rec.getMax(sResponse[EVACTextureTempUDPGet]).value())
-										.resp_mean(rec.getMean(sResponse[EVACTextureTempUDPGet]).value());
-			}
-			if (!compact_output
-				|| rec.getSum(sEnqueued[EVACTextureNonTempHTTPGet]) 
-				|| rec.getSum(sDequeued[EVACTextureNonTempHTTPGet])
-				|| rec.getSum(sResponse[EVACTextureNonTempHTTPGet]).value())
-			{
-				r.get_texture_non_temp_http	.enqueued(rec.getSum(sEnqueued[EVACTextureNonTempHTTPGet]))
-											.dequeued(rec.getSum(sDequeued[EVACTextureNonTempHTTPGet]))
-											.resp_count(rec.getSum(sResponse[EVACTextureNonTempHTTPGet]).value())
-											.resp_min(rec.getMin(sResponse[EVACTextureNonTempHTTPGet]).value())
-											.resp_max(rec.getMax(sResponse[EVACTextureNonTempHTTPGet]).value())
-											.resp_mean(rec.getMean(sResponse[EVACTextureNonTempHTTPGet]).value());
-			}
-
-			if (!compact_output
-				|| rec.getSum(sEnqueued[EVACTextureNonTempUDPGet]) 
-				|| rec.getSum(sDequeued[EVACTextureNonTempUDPGet])
-				|| rec.getSum(sResponse[EVACTextureNonTempUDPGet]).value())
-			{
-				r.get_texture_non_temp_udp	.enqueued(rec.getSum(sEnqueued[EVACTextureNonTempUDPGet]))
-											.dequeued(rec.getSum(sDequeued[EVACTextureNonTempUDPGet]))
-											.resp_count(rec.getSum(sResponse[EVACTextureNonTempUDPGet]).value())
-											.resp_min(rec.getMin(sResponse[EVACTextureNonTempUDPGet]).value())
-											.resp_max(rec.getMax(sResponse[EVACTextureNonTempUDPGet]).value())
-											.resp_mean(rec.getMean(sResponse[EVACTextureNonTempUDPGet]).value());
-			}
-
-			if (!compact_output
-				|| rec.getSum(sEnqueued[EVACWearableUDPGet]) 
-				|| rec.getSum(sDequeued[EVACWearableUDPGet])
-				|| rec.getSum(sResponse[EVACWearableUDPGet]).value())
-			{
-				r.get_wearable_udp	.enqueued(rec.getSum(sEnqueued[EVACWearableUDPGet]))
-									.dequeued(rec.getSum(sDequeued[EVACWearableUDPGet]))
-									.resp_count(rec.getSum(sResponse[EVACWearableUDPGet]).value())
-									.resp_min(rec.getMin(sResponse[EVACWearableUDPGet]).value())
-									.resp_max(rec.getMax(sResponse[EVACWearableUDPGet]).value())
-									.resp_mean(rec.getMean(sResponse[EVACWearableUDPGet]).value());
-			}
-
-			if (!compact_output
-				|| rec.getSum(sEnqueued[EVACSoundUDPGet]) 
-				|| rec.getSum(sDequeued[EVACSoundUDPGet])
-				|| rec.getSum(sResponse[EVACSoundUDPGet]).value())
-			{
-				r.get_sound_udp	.enqueued(rec.getSum(sEnqueued[EVACSoundUDPGet]))
-								.dequeued(rec.getSum(sDequeued[EVACSoundUDPGet]))
-								.resp_count(rec.getSum(sResponse[EVACSoundUDPGet]).value())
-								.resp_min(rec.getMin(sResponse[EVACSoundUDPGet]).value())
-								.resp_max(rec.getMax(sResponse[EVACSoundUDPGet]).value())
-								.resp_mean(rec.getMean(sResponse[EVACSoundUDPGet]).value());
-			}
-
-			if (!compact_output
-				|| rec.getSum(sEnqueued[EVACGestureUDPGet]) 
-				|| rec.getSum(sDequeued[EVACGestureUDPGet])
-				|| rec.getSum(sResponse[EVACGestureUDPGet]).value())
-			{
-				r.get_gesture_udp	.enqueued(rec.getSum(sEnqueued[EVACGestureUDPGet]))
-									.dequeued(rec.getSum(sDequeued[EVACGestureUDPGet]))
-									.resp_count(rec.getSum(sResponse[EVACGestureUDPGet]).value())
-									.resp_min(rec.getMin(sResponse[EVACGestureUDPGet]).value())
-									.resp_max(rec.getMax(sResponse[EVACGestureUDPGet]).value())
-									.resp_mean(rec.getMean(sResponse[EVACGestureUDPGet]).value());
-			}
-
-			if (!compact_output
-				|| rec.getSum(sEnqueued[EVACOtherGet]) 
-				|| rec.getSum(sDequeued[EVACOtherGet])
-				|| rec.getSum(sResponse[EVACOtherGet]).value())
-			{
-				r.get_other	.enqueued(rec.getSum(sEnqueued[EVACOtherGet]))
-							.dequeued(rec.getSum(sDequeued[EVACOtherGet]))
-							.resp_count(rec.getSum(sResponse[EVACOtherGet]).value())
-							.resp_min(rec.getMin(sResponse[EVACOtherGet]).value())
-							.resp_max(rec.getMax(sResponse[EVACOtherGet]).value())
-							.resp_mean(rec.getMean(sResponse[EVACOtherGet]).value());
-			}
-
-			S32 fps = rec.getSum(LLStatViewer::FPS_SAMPLE);
-			if (!compact_output || fps != 0)
-			{
-				r.fps.count(fps);
-				r.fps.min(rec.getMin(LLStatViewer::FPS_SAMPLE));
-				r.fps.max(rec.getMax(LLStatViewer::FPS_SAMPLE));
-				r.fps.mean(rec.getMean(LLStatViewer::FPS_SAMPLE));
-			}
-			U32 grid_x(0), grid_y(0);
-			grid_from_region_handle(it->first, &grid_x, &grid_y);
-			r.grid_x(grid_x);
-			r.grid_y(grid_y);
-			r.duration(LLUnit::Microseconds<F64>(rec.getDuration()).value());
+			r.get_texture_temp_http	.enqueued(rec.getSum(sEnqueued[EVACTextureTempHTTPGet]))
+									.dequeued(rec.getSum(sDequeued[EVACTextureTempHTTPGet]))
+									.resp_count(rec.getSum(sResponse[EVACTextureTempHTTPGet]).value())
+									.resp_min(rec.getMin(sResponse[EVACTextureTempHTTPGet]).value())
+									.resp_max(rec.getMax(sResponse[EVACTextureTempHTTPGet]).value())
+									.resp_mean(rec.getMean(sResponse[EVACTextureTempHTTPGet]).value());
+		}
+		if (!compact_output
+			|| rec.getSum(sEnqueued[EVACTextureTempUDPGet]) 
+			|| rec.getSum(sDequeued[EVACTextureTempUDPGet])
+			|| rec.getSum(sResponse[EVACTextureTempUDPGet]).value())
+		{
+			r.get_texture_temp_udp	.enqueued(rec.getSum(sEnqueued[EVACTextureTempUDPGet]))
+									.dequeued(rec.getSum(sDequeued[EVACTextureTempUDPGet]))
+									.resp_count(rec.getSum(sResponse[EVACTextureTempUDPGet]).value())
+									.resp_min(rec.getMin(sResponse[EVACTextureTempUDPGet]).value())
+									.resp_max(rec.getMax(sResponse[EVACTextureTempUDPGet]).value())
+									.resp_mean(rec.getMean(sResponse[EVACTextureTempUDPGet]).value());
+		}
+		if (!compact_output
+			|| rec.getSum(sEnqueued[EVACTextureNonTempHTTPGet]) 
+			|| rec.getSum(sDequeued[EVACTextureNonTempHTTPGet])
+			|| rec.getSum(sResponse[EVACTextureNonTempHTTPGet]).value())
+		{
+			r.get_texture_non_temp_http	.enqueued(rec.getSum(sEnqueued[EVACTextureNonTempHTTPGet]))
+										.dequeued(rec.getSum(sDequeued[EVACTextureNonTempHTTPGet]))
+										.resp_count(rec.getSum(sResponse[EVACTextureNonTempHTTPGet]).value())
+										.resp_min(rec.getMin(sResponse[EVACTextureNonTempHTTPGet]).value())
+										.resp_max(rec.getMax(sResponse[EVACTextureNonTempHTTPGet]).value())
+										.resp_mean(rec.getMean(sResponse[EVACTextureNonTempHTTPGet]).value());
+		}
+
+		if (!compact_output
+			|| rec.getSum(sEnqueued[EVACTextureNonTempUDPGet]) 
+			|| rec.getSum(sDequeued[EVACTextureNonTempUDPGet])
+			|| rec.getSum(sResponse[EVACTextureNonTempUDPGet]).value())
+		{
+			r.get_texture_non_temp_udp	.enqueued(rec.getSum(sEnqueued[EVACTextureNonTempUDPGet]))
+										.dequeued(rec.getSum(sDequeued[EVACTextureNonTempUDPGet]))
+										.resp_count(rec.getSum(sResponse[EVACTextureNonTempUDPGet]).value())
+										.resp_min(rec.getMin(sResponse[EVACTextureNonTempUDPGet]).value())
+										.resp_max(rec.getMax(sResponse[EVACTextureNonTempUDPGet]).value())
+										.resp_mean(rec.getMean(sResponse[EVACTextureNonTempUDPGet]).value());
+		}
+
+		if (!compact_output
+			|| rec.getSum(sEnqueued[EVACWearableUDPGet]) 
+			|| rec.getSum(sDequeued[EVACWearableUDPGet])
+			|| rec.getSum(sResponse[EVACWearableUDPGet]).value())
+		{
+			r.get_wearable_udp	.enqueued(rec.getSum(sEnqueued[EVACWearableUDPGet]))
+								.dequeued(rec.getSum(sDequeued[EVACWearableUDPGet]))
+								.resp_count(rec.getSum(sResponse[EVACWearableUDPGet]).value())
+								.resp_min(rec.getMin(sResponse[EVACWearableUDPGet]).value())
+								.resp_max(rec.getMax(sResponse[EVACWearableUDPGet]).value())
+								.resp_mean(rec.getMean(sResponse[EVACWearableUDPGet]).value());
+		}
+
+		if (!compact_output
+			|| rec.getSum(sEnqueued[EVACSoundUDPGet]) 
+			|| rec.getSum(sDequeued[EVACSoundUDPGet])
+			|| rec.getSum(sResponse[EVACSoundUDPGet]).value())
+		{
+			r.get_sound_udp	.enqueued(rec.getSum(sEnqueued[EVACSoundUDPGet]))
+							.dequeued(rec.getSum(sDequeued[EVACSoundUDPGet]))
+							.resp_count(rec.getSum(sResponse[EVACSoundUDPGet]).value())
+							.resp_min(rec.getMin(sResponse[EVACSoundUDPGet]).value())
+							.resp_max(rec.getMax(sResponse[EVACSoundUDPGet]).value())
+							.resp_mean(rec.getMean(sResponse[EVACSoundUDPGet]).value());
+		}
+
+		if (!compact_output
+			|| rec.getSum(sEnqueued[EVACGestureUDPGet]) 
+			|| rec.getSum(sDequeued[EVACGestureUDPGet])
+			|| rec.getSum(sResponse[EVACGestureUDPGet]).value())
+		{
+			r.get_gesture_udp	.enqueued(rec.getSum(sEnqueued[EVACGestureUDPGet]))
+								.dequeued(rec.getSum(sDequeued[EVACGestureUDPGet]))
+								.resp_count(rec.getSum(sResponse[EVACGestureUDPGet]).value())
+								.resp_min(rec.getMin(sResponse[EVACGestureUDPGet]).value())
+								.resp_max(rec.getMax(sResponse[EVACGestureUDPGet]).value())
+								.resp_mean(rec.getMean(sResponse[EVACGestureUDPGet]).value());
 		}
+
+		if (!compact_output
+			|| rec.getSum(sEnqueued[EVACOtherGet]) 
+			|| rec.getSum(sDequeued[EVACOtherGet])
+			|| rec.getSum(sResponse[EVACOtherGet]).value())
+		{
+			r.get_other	.enqueued(rec.getSum(sEnqueued[EVACOtherGet]))
+						.dequeued(rec.getSum(sDequeued[EVACOtherGet]))
+						.resp_count(rec.getSum(sResponse[EVACOtherGet]).value())
+						.resp_min(rec.getMin(sResponse[EVACOtherGet]).value())
+						.resp_max(rec.getMax(sResponse[EVACOtherGet]).value())
+						.resp_mean(rec.getMean(sResponse[EVACOtherGet]).value());
+		}
+
+		S32 fps = rec.getSum(LLStatViewer::FPS_SAMPLE);
+		if (!compact_output || fps != 0)
+		{
+			r.fps.count(fps);
+			r.fps.min(rec.getMin(LLStatViewer::FPS_SAMPLE));
+			r.fps.max(rec.getMax(LLStatViewer::FPS_SAMPLE));
+			r.fps.mean(rec.getMean(LLStatViewer::FPS_SAMPLE));
+		}
+		U32 grid_x(0), grid_y(0);
+		grid_from_region_handle(it->first, &grid_x, &grid_y);
+		r.grid_x(grid_x);
+		r.grid_y(grid_y);
+		r.duration(LLUnit::Microseconds<F64>(rec.getDuration()).value());
 	}
 
 	stats.duration(mCurRecording ? LLUnit::Microseconds<F64>(mCurRecording->getDuration()).value() : 0.0);
-	//stats.avatar.setProvided(true);
+	stats.avatar.setProvided(true);
 
 	for (S32 rez_stat=0; rez_stat < mAvatarRezStates.size(); ++rez_stat)
 	{
@@ -453,7 +448,12 @@ LLSD LLViewerAssetStats::asLLSD(bool compact_output)
 	LLSD sd;
 	AssetStats stats;
 	getStats(stats, compact_output);
-	parser.writeSD(sd, stats);
+	LLInitParam::predicate_rule_t rule = LLInitParam::default_parse_rules();
+	if (!compact_output)
+	{
+		rule.allow(LLInitParam::EMPTY);
+	}
+	parser.writeSD(sd, stats, rule);
 	return sd;
 }
 
diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h
index 2f50c527304..f1ce3aeaa2f 100755
--- a/indra/newview/llviewerassetstats.h
+++ b/indra/newview/llviewerassetstats.h
@@ -114,7 +114,6 @@ class LLViewerAssetStats
 
 	struct RegionStats : public LLInitParam::Block<RegionStats>
 	{
-		Optional<LLInitParam::Flag>				empty;
 		Optional<AssetRequestType>	get_texture_temp_http,
 									get_texture_temp_udp,
 									get_texture_non_temp_http,
-- 
GitLab