summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorBrad Payne (Vir Linden) <vir@lindenlab.com>2022-05-11 21:19:55 +0100
committerBrad Payne (Vir Linden) <vir@lindenlab.com>2022-05-11 21:19:55 +0100
commit3915c8417d6d6c493c175d1e99bb4776a8e25fd0 (patch)
treee551627798833b9d071fc5da861dc05779d79601 /indra
parentbc7e2fb7e7f7527b522bdf6f4c791f3b660485e2 (diff)
SL-17243 - ViewerStats includes details on warning conditions in inventory, if any are encountered.
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/llinventorymodel.cpp113
-rw-r--r--indra/newview/llinventorymodel.h43
2 files changed, 102 insertions, 54 deletions
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 37500176ea..0e619991e6 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -135,15 +135,7 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
///----------------------------------------------------------------------------
/// Class LLInventoryValidationInfo
///----------------------------------------------------------------------------
-LLInventoryValidationInfo::LLInventoryValidationInfo():
- mFatalErrorCount(0),
- mWarningCount(0),
- mLoopCount(0),
- mOrphanedCount(0),
- mInitialized(false),
- mFatalNoRootFolder(false),
- mFatalNoLibraryRootFolder(false),
- mFatalQADebugMode(false)
+LLInventoryValidationInfo::LLInventoryValidationInfo()
{
}
@@ -173,6 +165,26 @@ void LLInventoryValidationInfo::asLLSD(LLSD& sd) const
sd["fatal_no_root_folder"] = mFatalNoRootFolder;
sd["fatal_no_library_root_folder"] = mFatalNoLibraryRootFolder;
sd["fatal_qa_debug_mode"] = mFatalQADebugMode;
+ if (mWarningCount>0)
+ {
+ sd["warnings"] = LLSD::emptyArray();
+ sd["warnings"]["category_map_size"] = mWarningCategoryMapSize;
+ sd["warnings"]["null_cat"] = mWarningNullCat;
+ sd["warnings"]["unknown_ancestor_status"] = mWarningUnknownAncestorStatus;
+ sd["warnings"]["cat_id_index_mismatch"] = mWarningCatIDIndexMismatch;
+ sd["warnings"]["null_parent"] = mWarningNullParent;
+ sd["warnings"]["direct_descendents"] = mWarningDirectDescendents;
+ sd["warnings"]["invalid_descendent_count"] = mWarningInvalidDescendentCount;
+ sd["warnings"]["null_item_at_index"] = mWarningNullItemAtIndex;
+ sd["warnings"]["wrong_parent_for_item"] = mWarningWrongParentForItem;
+ sd["warnings"]["item_not_in_top_map"] = mWarningItemNotInTopMap;
+ sd["warnings"]["topmost_ancestor_not_found"] = mWarningTopmostAncestorNotFound;
+ sd["warnings"]["topmost_ancestor_not_recognized"] = mWarningTopmostAncestorNotRecognized;
+ sd["warnings"]["item_id_mismatch"] = mWarningItemIDMismatch;
+ sd["warnings"]["missing_system_folder_can_create"] = mWarningMissingSystemFolderCanCreate;
+ sd["warnings"]["non_fatal_system_duplicate_under_root"] = mWarningNonFatalSystemDuplicateUnderRoot;
+ sd["warnings"]["non_fatal_system_duplicate_elsewhere"] = mWarningSystemDuplicateElsewhere;
+ }
if (mMissingRequiredSystemFolders.size()>0)
{
sd["missing_system_folders"] = LLSD::emptyArray();
@@ -344,13 +356,13 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL
return NULL;
}
-LLInventoryModel::EAnscestorResult LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const
+LLInventoryModel::EAncestorResult LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const
{
LLInventoryObject *object = getObject(object_id);
if (!object)
{
LL_WARNS(LOG_INV) << "Unable to trace topmost ancestor, initial object " << object_id << " does not exist" << LL_ENDL;
- return ANSCESTOR_MISSING;
+ return ANCESTOR_MISSING;
}
std::set<LLUUID> object_ids{ object_id }; // loop protection
@@ -360,19 +372,19 @@ LLInventoryModel::EAnscestorResult LLInventoryModel::getObjectTopmostAncestor(co
if (object_ids.find(parent_id) != object_ids.end())
{
LL_WARNS(LOG_INV) << "Detected a loop on an object " << parent_id << " when searching for ancestor of " << object_id << LL_ENDL;
- return ANSCESTOR_LOOP;
+ return ANCESTOR_LOOP;
}
object_ids.insert(parent_id);
LLInventoryObject *parent_object = getObject(parent_id);
if (!parent_object)
{
LL_WARNS(LOG_INV) << "unable to trace topmost ancestor of " << object_id << ", missing item for uuid " << parent_id << LL_ENDL;
- return ANSCESTOR_MISSING;
+ return ANCESTOR_MISSING;
}
object = parent_object;
}
result = object->getUUID();
- return ANSCESTOR_OK;
+ return ANCESTOR_OK;
}
// Get the object by id. Returns NULL if not found.
@@ -3899,7 +3911,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LLPointer<LLInventoryValidationInfo> validation_info = new LLInventoryValidationInfo;
S32 fatal_errs = 0;
- S32 warnings = 0;
+ S32 warning_count= 0;
S32 loops = 0;
S32 orphaned = 0;
@@ -3922,7 +3934,9 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
// ParentChild should be one larger because of the special entry for null uuid.
LL_INFOS("Inventory") << "unexpected sizes: cat map size " << mCategoryMap.size()
<< " parent/child " << mParentChildCategoryTree.size() << LL_ENDL;
- warnings++;
+
+ validation_info->mWarningCategoryMapSize++;
+ warning_count++;
}
S32 cat_lock = 0;
S32 item_lock = 0;
@@ -3941,32 +3955,35 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
if (!cat)
{
LL_WARNS("Inventory") << "null cat" << LL_ENDL;
- warnings++;
+ validation_info->mWarningNullCat++;
+ warning_count++;
continue;
}
LLUUID topmost_ancestor_id;
// Will leave as null uuid on failure
- EAnscestorResult res = getObjectTopmostAncestor(cat_id, topmost_ancestor_id);
+ EAncestorResult res = getObjectTopmostAncestor(cat_id, topmost_ancestor_id);
switch (res)
{
- case ANSCESTOR_MISSING:
+ case ANCESTOR_MISSING:
orphaned++;
break;
- case ANSCESTOR_LOOP:
+ case ANCESTOR_LOOP:
loops++;
break;
- case ANSCESTOR_OK:
+ case ANCESTOR_OK:
break;
default:
LL_WARNS("Inventory") << "Unknown ancestor error for " << cat_id << LL_ENDL;
- warnings++;
+ validation_info->mWarningUnknownAncestorStatus++;
+ warning_count++;
break;
}
if (cat_id != cat->getUUID())
{
LL_WARNS("Inventory") << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL;
- warnings++;
+ validation_info->mWarningCatIDIndexMismatch++;
+ warning_count++;
}
if (cat->getParentUUID().isNull())
@@ -3976,7 +3993,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
LL_WARNS("Inventory") << "cat " << cat_id << " has no parent, but is not root ("
<< getRootFolderID() << ") or library root ("
<< getLibraryRootFolderID() << ")" << LL_ENDL;
- warnings++;
+ validation_info->mWarningNullParent++;
+ warning_count++;
}
}
cat_array_t* cats;
@@ -3985,7 +4003,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
if (!cats || !items)
{
LL_WARNS("Inventory") << "invalid direct descendents for " << cat_id << LL_ENDL;
- warnings++;
+ validation_info->mWarningDirectDescendents++;
+ warning_count++;
continue;
}
if (cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
@@ -4003,7 +4022,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
<< " cached " << cat->getDescendentCount()
<< " expected " << cats->size() << "+" << items->size()
<< "=" << cats->size() +items->size() << LL_ENDL;
- warnings++;
+ validation_info->mWarningInvalidDescendentCount++;
+ warning_count++;
}
}
if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
@@ -4027,7 +4047,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
if (!item)
{
LL_WARNS("Inventory") << "null item at index " << i << " for cat " << cat_id << LL_ENDL;
- warnings++;
+ validation_info->mWarningNullItemAtIndex++;
+ warning_count++;
continue;
}
@@ -4038,7 +4059,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
LL_WARNS("Inventory") << "wrong parent for " << item_id << " found "
<< item->getParentUUID() << " expected " << cat_id
<< LL_ENDL;
- warnings++;
+ validation_info->mWarningWrongParentForItem++;
+ warning_count++;
}
@@ -4048,7 +4070,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LL_WARNS("Inventory") << "item " << item_id << " found as child of "
<< cat_id << " but not in top level mItemMap" << LL_ENDL;
- warnings++;
+ validation_info->mWarningItemNotInTopMap++;
+ warning_count++;
}
else
{
@@ -4062,11 +4085,12 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
// Topmost ancestor should be root or library.
LLUUID topmost_ancestor_id;
- EAnscestorResult found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
- if (found != ANSCESTOR_OK)
+ EAncestorResult found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
+ if (found != ANCESTOR_OK)
{
LL_WARNS("Inventory") << "unable to find topmost ancestor for " << item_id << LL_ENDL;
- warnings++;
+ validation_info->mWarningTopmostAncestorNotFound++;
+ warning_count++;
}
else
{
@@ -4077,7 +4101,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
<< " got " << topmost_ancestor_id
<< " expected " << getRootFolderID()
<< " or " << getLibraryRootFolderID() << LL_ENDL;
- warnings++;
+ validation_info->mWarningTopmostAncestorNotRecognized++;
+ warning_count++;
}
}
}
@@ -4120,7 +4145,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
LLFolderType::EType folder_type = cat->getPreferredType();
bool cat_is_in_library = false;
LLUUID topmost_id;
- if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) == ANSCESTOR_OK && topmost_id == getLibraryRootFolderID())
+ if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) == ANCESTOR_OK && topmost_id == getLibraryRootFolderID())
{
cat_is_in_library = true;
}
@@ -4153,7 +4178,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
if (item->getUUID() != item_id)
{
LL_WARNS("Inventory") << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL;
- warnings++;
+ validation_info->mWarningItemIDMismatch++;
+ warning_count++;
}
const LLUUID& parent_id = item->getParentUUID();
@@ -4289,13 +4315,15 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
if (is_automatic)
{
LL_WARNS("Inventory") << "Fatal inventory corruption: cannot create system folder of type " << ft << LL_ENDL;
- fatal_errs++;
validation_info->mMissingRequiredSystemFolders.insert(folder_type);
+ fatal_errs++;
}
else
{
// Can create, and will when needed.
- warnings++;
+ // (Not sure this is really a warning, but worth logging)
+ validation_info->mWarningMissingSystemFolderCanCreate++;
+ warning_count++;
}
}
else if (count_under_root > 1)
@@ -4306,6 +4334,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
// It is a fatal problem or can lead to fatal problems for COF,
// outfits, trash and other non-automatic folders.
+ validation_info->mFatalSystemDuplicate++;
fatal_errs++;
}
else
@@ -4313,13 +4342,15 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
// For automatic folders it's not a fatal issue and shouldn't
// break inventory or other functionality further
// Exception: FT_SETTINGS is not automatic, but only deserves a warning.
- warnings++;
+ validation_info->mWarningNonFatalSystemDuplicateUnderRoot++;
+ warning_count++;
}
}
if (count_elsewhere > 0)
{
LL_WARNS("Inventory") << "Found " << count_elsewhere << " extra folders of type " << ft << " outside of root" << LL_ENDL;
- warnings++;
+ validation_info->mWarningSystemDuplicateElsewhere++;
+ warning_count++;
}
}
}
@@ -4341,10 +4372,10 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
// FIXME need to fail login and tell user to retry, contact support if problem persists.
bool valid = (fatal_errs == 0);
- LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatal_errs << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL;
+ LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatal_errs << ", warnings: " << warning_count << ", valid: " << valid << LL_ENDL;
validation_info->mFatalErrorCount = fatal_errs;
- validation_info->mWarningCount = warnings;
+ validation_info->mWarningCount = warning_count;
validation_info->mLoopCount = loops;
validation_info->mOrphanedCount = orphaned;
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index eeec89bfb0..e19f41bd24 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -66,14 +66,31 @@ public:
void asLLSD(LLSD& sd) const;
- S32 mFatalErrorCount;
- S32 mWarningCount;
- S32 mLoopCount; // Presence of folders whose ansestors loop onto themselves
- S32 mOrphanedCount; // Missing or orphaned items, links and folders
- bool mInitialized;
- bool mFatalNoRootFolder;
- bool mFatalNoLibraryRootFolder;
- bool mFatalQADebugMode;
+ S32 mWarningCount{0};
+ S32 mWarningCategoryMapSize{0};
+ S32 mWarningNullCat{0};
+ S32 mWarningUnknownAncestorStatus{0};
+ S32 mWarningCatIDIndexMismatch{0};
+ S32 mWarningNullParent{0};
+ S32 mWarningDirectDescendents{0};
+ S32 mWarningInvalidDescendentCount{0};
+ S32 mWarningNullItemAtIndex{0};
+ S32 mWarningWrongParentForItem{0};
+ S32 mWarningItemNotInTopMap{0};
+ S32 mWarningTopmostAncestorNotFound{0};
+ S32 mWarningTopmostAncestorNotRecognized{0};
+ S32 mWarningItemIDMismatch{0};
+ S32 mWarningMissingSystemFolderCanCreate{0};
+ S32 mWarningNonFatalSystemDuplicateUnderRoot{0};
+ S32 mWarningSystemDuplicateElsewhere{0};
+ S32 mLoopCount{0}; // Presence of folders whose ancestors loop onto themselves
+ S32 mOrphanedCount{0}; // Missing or orphaned items, links and folders
+ bool mInitialized{false};
+ S32 mFatalErrorCount{0};
+ bool mFatalNoRootFolder{false};
+ S32 mFatalSystemDuplicate{0};
+ bool mFatalNoLibraryRootFolder{false};
+ bool mFatalQADebugMode{false};
std::set<LLFolderType::EType> mMissingRequiredSystemFolders;
std::set<LLFolderType::EType> mDuplicateRequiredSystemFolders;
};
@@ -286,13 +303,13 @@ public:
// Check if one object has a parent chain up to the category specified by UUID.
BOOL isObjectDescendentOf(const LLUUID& obj_id, const LLUUID& cat_id) const;
- enum EAnscestorResult{
- ANSCESTOR_OK = 0,
- ANSCESTOR_MISSING = 1,
- ANSCESTOR_LOOP = 2,
+ enum EAncestorResult{
+ ANCESTOR_OK = 0,
+ ANCESTOR_MISSING = 1,
+ ANCESTOR_LOOP = 2,
};
// Follow parent chain to the top.
- EAnscestorResult getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
+ EAncestorResult getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
//--------------------------------------------------------------------
// Find