summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/llinventorymodel.cpp89
-rw-r--r--indra/newview/llinventorymodel.h11
2 files changed, 77 insertions, 23 deletions
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index ea22750c1f..8ddba510b4 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -138,6 +138,8 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
LLInventoryValidationInfo::LLInventoryValidationInfo():
mFatalErrorCount(0),
mWarningCount(0),
+ mLoopCount(0),
+ mOrphanedCount(0),
mInitialized(false),
mFatalNoRootFolder(false),
mFatalNoLibraryRootFolder(false),
@@ -147,7 +149,10 @@ LLInventoryValidationInfo::LLInventoryValidationInfo():
void LLInventoryValidationInfo::toOstream(std::ostream& os) const
{
- os << "mFatalErrorCount " << mFatalErrorCount << " mWarningCount " << mWarningCount;
+ os << "mFatalErrorCount " << mFatalErrorCount
+ << " mWarningCount " << mWarningCount
+ << " mLoopCount " << mLoopCount
+ << " mOrphanedCount " << mOrphanedCount;
}
@@ -161,6 +166,8 @@ void LLInventoryValidationInfo::asLLSD(LLSD& sd) const
{
sd["fatal_error_count"] = mFatalErrorCount;
sd["warning_count"] = mWarningCount;
+ sd["loop_count"] = mLoopCount;
+ sd["orphaned_count"] = mOrphanedCount;
sd["initialized"] = mInitialized;
sd["missing_system_folders_count"] = LLSD::Integer(mMissingRequiredSystemFolders.size());
sd["fatal_no_root_folder"] = mFatalNoRootFolder;
@@ -337,13 +344,13 @@ const LLViewerInventoryCategory* LLInventoryModel::getFirstDescendantOf(const LL
return NULL;
}
-bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const
+LLInventoryModel::EAnscestorResult 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 false;
+ return ANSCESTOR_MISSING;
}
std::set<LLUUID> object_ids{ object_id }; // loop protection
@@ -353,19 +360,19 @@ bool LLInventoryModel::getObjectTopmostAncestor(const LLUUID& object_id, LLUUID&
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 false;
+ return ANSCESTOR_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 false;
+ return ANSCESTOR_MISSING;
}
object = parent_object;
}
result = object->getUUID();
- return true;
+ return ANSCESTOR_OK;
}
// Get the object by id. Returns NULL if not found.
@@ -3891,20 +3898,23 @@ void LLInventoryModel::dumpInventory() const
LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LLPointer<LLInventoryValidationInfo> validation_info = new LLInventoryValidationInfo;
- S32 fatalities = 0;
+ S32 fatal_errs = 0;
S32 warnings = 0;
+ S32 loops = 0;
+ S32 orphaned = 0;
if (getRootFolderID().isNull())
{
LL_WARNS("Inventory") << "Fatal inventory corruption: no root folder id" << LL_ENDL;
validation_info->mFatalNoRootFolder = true;
- fatalities++;
+ fatal_errs++;
}
if (getLibraryRootFolderID().isNull())
{
+ // Probably shouldn't be a fatality, inventory can function without a library
LL_WARNS("Inventory") << "Fatal inventory corruption: no library root folder id" << LL_ENDL;
validation_info->mFatalNoLibraryRootFolder = true;
- fatalities++;
+ fatal_errs++;
}
if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size())
@@ -3936,7 +3946,23 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
}
LLUUID topmost_ancestor_id;
// Will leave as null uuid on failure
- getObjectTopmostAncestor(cat_id, topmost_ancestor_id);
+ EAnscestorResult res = getObjectTopmostAncestor(cat_id, topmost_ancestor_id);
+ switch (res)
+ {
+ case ANSCESTOR_MISSING:
+ orphaned++;
+ break;
+ case ANSCESTOR_LOOP:
+ loops++;
+ break;
+ case ANSCESTOR_OK:
+ break;
+ default:
+ LL_WARNS("Inventory") << "Unknown ancestor error for " << cat_id << LL_ENDL;
+ warnings++;
+ break;
+ }
+
if (cat_id != cat->getUUID())
{
LL_WARNS("Inventory") << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL;
@@ -4036,8 +4062,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
// Topmost ancestor should be root or library.
LLUUID topmost_ancestor_id;
- bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
- if (!found)
+ EAnscestorResult found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
+ if (found != ANSCESTOR_OK)
{
LL_WARNS("Inventory") << "unable to find topmost ancestor for " << item_id << LL_ENDL;
warnings++;
@@ -4067,7 +4093,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName()
<< "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL;
- warnings++;
+ orphaned++;
}
else
{
@@ -4085,6 +4111,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LL_WARNS("Inventory") << "cat " << cat_id << " name [" << cat->getName()
<< "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL;
+ orphaned++;
}
}
}
@@ -4093,7 +4120,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) && topmost_id == getLibraryRootFolderID())
+ if (getObjectTopmostAncestor(cat->getUUID(),topmost_id) == ANSCESTOR_OK && topmost_id == getLibraryRootFolderID())
{
cat_is_in_library = true;
}
@@ -4133,6 +4160,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
if (parent_id.isNull())
{
LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL;
+ orphaned++;
}
else
{
@@ -4143,6 +4171,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName()
<< "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL;
+ orphaned++;
}
else
{
@@ -4159,6 +4188,7 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
{
LL_WARNS("Inventory") << "item " << item_id << " name [" << item->getName()
<< "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL;
+ orphaned++;
}
}
@@ -4176,15 +4206,18 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
LL_WARNS("Inventory") << "link " << item->getUUID() << " type " << item->getActualType()
<< " missing backlink info at target_id " << target_id
<< LL_ENDL;
+ orphaned++;
}
// Links should have referents.
if (item->getActualType() == LLAssetType::AT_LINK && !target_item)
{
LL_WARNS("Inventory") << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+ orphaned++;
}
else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat)
{
LL_WARNS("Inventory") << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+ orphaned++;
}
if (target_item && target_item->getIsLinkType())
{
@@ -4256,8 +4289,8 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
if (is_automatic)
{
LL_WARNS("Inventory") << "Fatal inventory corruption: cannot create system folder of type " << ft << LL_ENDL;
- fatalities++;
- validation_info->mMissingRequiredSystemFolders.insert(LLFolderType::EType(ft));
+ fatal_errs++;
+ validation_info->mMissingRequiredSystemFolders.insert(folder_type);
}
else
{
@@ -4268,8 +4301,20 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
else if (count_under_root > 1)
{
LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL;
- validation_info->mDuplicateRequiredSystemFolders.insert(LLFolderType::EType(ft));
- fatalities++;
+ validation_info->mDuplicateRequiredSystemFolders.insert(folder_type);
+ if (!is_automatic)
+ {
+ // It is a fatal problem or can lead to fatal problems for COF,
+ // outfits and trash and other non-automatic folders.
+ // Exception: FT_SETTINGS likely only deserves a warning.
+ fatal_errs++;
+ }
+ else
+ {
+ // For automatic folders it's not a fatal issue and shouldn't
+ // break inventory or other functionality further
+ warnings++;
+ }
}
if (count_elsewhere > 0)
{
@@ -4295,11 +4340,13 @@ LLPointer<LLInventoryValidationInfo> LLInventoryModel::validate() const
}
// FIXME need to fail login and tell user to retry, contact support if problem persists.
- bool valid = (fatalities == 0);
- LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatalities << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL;
+ bool valid = (fatal_errs == 0);
+ LL_INFOS("Inventory") << "Validate done, fatal errors: " << fatal_errs << ", warnings: " << warnings << ", valid: " << valid << LL_ENDL;
- validation_info->mFatalErrorCount = fatalities;
+ validation_info->mFatalErrorCount = fatal_errs;
validation_info->mWarningCount = warnings;
+ validation_info->mLoopCount = loops;
+ validation_info->mOrphanedCount = orphaned;
return validation_info;
}
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index e81652820f..eeec89bfb0 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -68,6 +68,8 @@ public:
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;
@@ -283,9 +285,14 @@ 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,
+ };
// Follow parent chain to the top.
- bool getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
+ EAnscestorResult getObjectTopmostAncestor(const LLUUID& object_id, LLUUID& result) const;
//--------------------------------------------------------------------
// Find