Skip to content

Commit 07665b7

Browse files
committed
Fix cache dehydration
1 parent 61778b4 commit 07665b7

File tree

2 files changed

+191
-17
lines changed

2 files changed

+191
-17
lines changed

indra/newview/llinventorymodel.cpp

Lines changed: 148 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include <typeinfo>
3030
#include <random>
31+
#include <set>
3132

3233
#include "llinventorymodel.h"
3334

@@ -125,16 +126,27 @@ bool LLCanCache::operator()(LLInventoryCategory* cat, LLInventoryItem* item)
125126
{
126127
// HACK: downcast
127128
LLViewerInventoryCategory* c = (LLViewerInventoryCategory*)cat;
128-
if(c->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
129+
130+
bool descendents_match = true;
131+
if (c->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
129132
{
130-
S32 descendents_server = c->getDescendentCount();
131-
S32 descendents_actual = c->getViewerDescendentCount();
132-
if(descendents_server == descendents_actual)
133+
const S32 descendents_server = c->getDescendentCount();
134+
const S32 descendents_actual = c->getViewerDescendentCount();
135+
descendents_match = (descendents_server == descendents_actual);
136+
137+
if (!descendents_match)
133138
{
134-
mCachedCatIDs.insert(c->getUUID());
135-
rv = true;
139+
LL_DEBUGS("AsyncInventory") << "Caching category with mismatched descendents"
140+
<< " cat_id=" << c->getUUID()
141+
<< " name=\"" << c->getName() << "\""
142+
<< " server_descendents=" << descendents_server
143+
<< " viewer_descendents=" << descendents_actual
144+
<< LL_ENDL;
136145
}
137146
}
147+
148+
mCachedCatIDs.insert(c->getUUID());
149+
rv = true;
138150
}
139151
return rv;
140152
}
@@ -2411,6 +2423,68 @@ void LLInventoryModel::cache(
24112423
items,
24122424
INCLUDE_TRASH,
24132425
can_cache);
2426+
2427+
std::set<LLUUID> cached_category_ids;
2428+
std::set<LLUUID> cached_item_ids;
2429+
for (auto& cat_ptr : categories)
2430+
{
2431+
if (cat_ptr.notNull())
2432+
{
2433+
cached_category_ids.insert(cat_ptr->getUUID());
2434+
}
2435+
}
2436+
for (auto& item_ptr : items)
2437+
{
2438+
if (item_ptr.notNull())
2439+
{
2440+
cached_item_ids.insert(item_ptr->getUUID());
2441+
}
2442+
}
2443+
2444+
// Fallback pass: ensure every known category/item under the root is persisted
2445+
// even if the parent/child map failed to enumerate it.
2446+
for (auto& entry : mCategoryMap)
2447+
{
2448+
LLViewerInventoryCategory* cat = entry.second;
2449+
if (!cat)
2450+
{
2451+
continue;
2452+
}
2453+
const LLUUID& cat_id = cat->getUUID();
2454+
if (cached_category_ids.count(cat_id) != 0)
2455+
{
2456+
continue;
2457+
}
2458+
if (!isObjectDescendentOf(cat_id, parent_folder_id))
2459+
{
2460+
continue;
2461+
}
2462+
if (can_cache(cat, NULL))
2463+
{
2464+
categories.push_back(cat);
2465+
cached_category_ids.insert(cat_id);
2466+
}
2467+
}
2468+
2469+
for (auto& entry : mItemMap)
2470+
{
2471+
LLViewerInventoryItem* item = entry.second;
2472+
if (!item)
2473+
{
2474+
continue;
2475+
}
2476+
const LLUUID& item_id = item->getUUID();
2477+
if (cached_item_ids.count(item_id) != 0)
2478+
{
2479+
continue;
2480+
}
2481+
if (!isObjectDescendentOf(item_id, parent_folder_id))
2482+
{
2483+
continue;
2484+
}
2485+
items.push_back(item);
2486+
cached_item_ids.insert(item_id);
2487+
}
24142488
// Use temporary file to avoid potential conflicts with other
24152489
// instances (even a 'read only' instance unzips into a file)
24162490
std::string temp_file = gDirUtilp->getTempFilename();
@@ -3097,6 +3171,8 @@ bool LLInventoryModel::loadSkeletonFromCacheOnly(const LLUUID& owner_id)
30973171
const S32 NO_VERSION = LLViewerInventoryCategory::VERSION_UNKNOWN;
30983172

30993173
size_t cached_category_count = 0;
3174+
size_t cached_category_unknown_version = 0;
3175+
size_t cached_category_marked_refresh = 0;
31003176
for (auto& cat : categories)
31013177
{
31023178
if (!cat)
@@ -3110,13 +3186,22 @@ bool LLInventoryModel::loadSkeletonFromCacheOnly(const LLUUID& owner_id)
31103186
const bool requires_refresh = (cached_version == NO_VERSION)
31113187
|| (categories_to_update.find(cat->getUUID()) != categories_to_update.end());
31123188
cat->setVersion(requires_refresh ? NO_VERSION : cached_version);
3189+
if (requires_refresh)
3190+
{
3191+
++cached_category_marked_refresh;
3192+
}
3193+
if (cached_version == NO_VERSION)
3194+
{
3195+
++cached_category_unknown_version;
3196+
}
31133197
addCategory(cat);
31143198
++child_counts[cat->getParentUUID()];
31153199
++cached_category_count;
31163200
}
31173201

31183202
cat_map_t::iterator unparented = mCategoryMap.end();
31193203
size_t cached_item_count = 0;
3204+
size_t items_missing_parent = 0;
31203205
for (auto& item_ptr : items)
31213206
{
31223207
LLViewerInventoryItem* item = item_ptr.get();
@@ -3132,8 +3217,14 @@ bool LLInventoryModel::loadSkeletonFromCacheOnly(const LLUUID& owner_id)
31323217
++child_counts[item->getParentUUID()];
31333218
++cached_item_count;
31343219
}
3220+
else
3221+
{
3222+
++items_missing_parent;
3223+
}
31353224
}
31363225

3226+
const size_t category_map_size_post_load = mCategoryMap.size();
3227+
31373228
for (auto& entry : child_counts)
31383229
{
31393230
const cat_map_t::iterator cit = mCategoryMap.find(entry.first);
@@ -3159,9 +3250,14 @@ bool LLInventoryModel::loadSkeletonFromCacheOnly(const LLUUID& owner_id)
31593250

31603251
categories.clear();
31613252

3162-
LL_INFOS(LOG_INV) << "Loaded cache-only skeleton for " << owner_id
3163-
<< " with " << cached_category_count << " categories and "
3164-
<< cached_item_count << " items." << LL_ENDL;
3253+
LL_INFOS("AsyncInventory") << "Loaded cache-only skeleton for " << owner_id
3254+
<< " categories_from_cache=" << cached_category_count
3255+
<< " categories_unknown_version=" << cached_category_unknown_version
3256+
<< " categories_marked_refresh=" << cached_category_marked_refresh
3257+
<< " items_from_cache=" << cached_item_count
3258+
<< " items_missing_parent=" << items_missing_parent
3259+
<< " category_map_size_post_load=" << category_map_size_post_load
3260+
<< LL_ENDL;
31653261

31663262
return cached_category_count > 0;
31673263
}
@@ -3236,6 +3332,7 @@ void LLInventoryModel::buildParentChildMap(bool run_validation)
32363332
S32 i;
32373333
S32 lost = 0;
32383334
cat_array_t lost_cats;
3335+
size_t tree_links_inserted = 0;
32393336
for (auto& cat : cats)
32403337
{
32413338
catsp = getUnlockedCatArray(cat->getParentUUID());
@@ -3246,6 +3343,7 @@ void LLInventoryModel::buildParentChildMap(bool run_validation)
32463343
cat->getPreferredType() == LLFolderType::FT_ROOT_INVENTORY ))
32473344
{
32483345
catsp->push_back(cat);
3346+
++tree_links_inserted;
32493347
}
32503348
else
32513349
{
@@ -3261,6 +3359,7 @@ void LLInventoryModel::buildParentChildMap(bool run_validation)
32613359
lost_cats.push_back(cat);
32623360
}
32633361
}
3362+
const S32 lost_categories = lost;
32643363
if(lost)
32653364
{
32663365
LL_WARNS(LOG_INV) << "Found " << lost << " lost categories." << LL_ENDL;
@@ -3299,6 +3398,7 @@ void LLInventoryModel::buildParentChildMap(bool run_validation)
32993398
if(catsp)
33003399
{
33013400
catsp->push_back(cat);
3401+
++tree_links_inserted;
33023402
}
33033403
else
33043404
{
@@ -3314,6 +3414,7 @@ void LLInventoryModel::buildParentChildMap(bool run_validation)
33143414
// have to do is iterate over the items and put them in the right
33153415
// place.
33163416
item_array_t items;
3417+
size_t item_links_inserted = 0;
33173418
if(!mItemMap.empty())
33183419
{
33193420
LLPointer<LLViewerInventoryItem> item;
@@ -3331,6 +3432,7 @@ void LLInventoryModel::buildParentChildMap(bool run_validation)
33313432
if(itemsp)
33323433
{
33333434
itemsp->push_back(item);
3435+
++item_links_inserted;
33343436
}
33353437
else
33363438
{
@@ -3348,6 +3450,7 @@ void LLInventoryModel::buildParentChildMap(bool run_validation)
33483450
if(itemsp)
33493451
{
33503452
itemsp->push_back(item);
3453+
++item_links_inserted;
33513454
}
33523455
else
33533456
{
@@ -3388,6 +3491,21 @@ void LLInventoryModel::buildParentChildMap(bool run_validation)
33883491
}
33893492
}
33903493

3494+
const size_t category_tree_nodes = mParentChildCategoryTree.size();
3495+
const size_t item_tree_nodes = mParentChildItemTree.size();
3496+
const S32 lost_items = lost;
3497+
3498+
LL_INFOS("AsyncInventory") << "ParentChildMap summary"
3499+
<< " category_map_size=" << mCategoryMap.size()
3500+
<< " category_tree_nodes=" << category_tree_nodes
3501+
<< " category_links=" << tree_links_inserted
3502+
<< " item_map_size=" << mItemMap.size()
3503+
<< " item_tree_nodes=" << item_tree_nodes
3504+
<< " item_links=" << item_links_inserted
3505+
<< " lost_categories=" << lost_categories
3506+
<< " lost_items=" << lost_items
3507+
<< LL_ENDL;
3508+
33913509
if (run_validation)
33923510
{
33933511
const LLUUID& agent_inv_root_id = gInventory.getRootFolderID();
@@ -3427,7 +3545,7 @@ void LLInventoryModel::buildParentChildMap(bool run_validation)
34273545
{
34283546
// Fatal inventory error. Will not be able to engage in many inventory operations.
34293547
// This should be followed by an error dialog leading to logout.
3430-
LL_WARNS("Inventory") << "Fatal errors were found in validate(): unable to initialize inventory! "
3548+
LL_WARNS("AsyncInventory") << "Fatal errors were found in validate(): unable to initialize inventory! "
34313549
<< "Will not be able to do normal inventory operations in this session."
34323550
<< LL_ENDL;
34333551
mIsAgentInvUsable = false;
@@ -3783,14 +3901,24 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
37833901
LLSD& cat_array = inventory["categories"];
37843902

37853903
S32 cat_count = 0;
3904+
S32 cat_unknown_version_count = 0;
37863905
for (auto& cat : categories)
37873906
{
3788-
if (cat->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN)
3907+
if (!cat)
37893908
{
3790-
LLSD sd;
3791-
cat->exportLLSD(sd);
3792-
cat_array.append(sd);
3793-
cat_count++;
3909+
continue;
3910+
}
3911+
3912+
// Persist folders even when their version is unknown so warm-cache
3913+
// hydrations retain the complete hierarchy; those folders will be
3914+
// marked for refresh on the next login.
3915+
LLSD sd;
3916+
cat->exportLLSD(sd);
3917+
cat_array.append(sd);
3918+
++cat_count;
3919+
if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
3920+
{
3921+
++cat_unknown_version_count;
37943922
}
37953923
}
37963924

@@ -3806,14 +3934,17 @@ bool LLInventoryModel::saveToFile(const std::string& filename,
38063934
fileSD << LLSDOStreamer<LLSDBinaryFormatter>(inventory) << std::endl;
38073935
if (fileSD.fail())
38083936
{
3809-
LL_WARNS(LOG_INV) << "Failed to write cache. Unable to save inventory to: " << filename << LL_ENDL;
3937+
LL_WARNS("AsyncInventory") << "Failed to write cache. Unable to save inventory to: " << filename << LL_ENDL;
38103938
return false;
38113939
}
38123940
fileSD.flush();
38133941

38143942
fileSD.close();
38153943

3816-
LL_INFOS(LOG_INV) << "Inventory saved: " << (S32)cat_count << " categories, " << (S32)it_count << " items." << LL_ENDL;
3944+
LL_INFOS("AsyncInventory") << "Inventory saved: categories=" << cat_count
3945+
<< " categories_unknown_version=" << cat_unknown_version_count
3946+
<< " items=" << (S32)it_count
3947+
<< LL_ENDL;
38173948
}
38183949
catch (...)
38193950
{

indra/newview/llstartup.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,13 @@ void LLAsyncInventorySkeletonLoader::evaluateChildren(const FetchRequest& reques
638638
{
639639
if (!should_fetch && child_cache_valid)
640640
{
641+
LL_INFOS("AsyncInventory") << "Async skeleton loader trusting cached essential folder"
642+
<< " cat_id=" << child_id
643+
<< " name=\"" << child->getName() << "\""
644+
<< " cached_version=" << cached_child_version
645+
<< " current_version=" << current_child_version
646+
<< " descendents=" << child->getDescendentCount()
647+
<< LL_ENDL;
641648
mFetchedCategories.insert(child_id);
642649
continue;
643650
}
@@ -655,9 +662,23 @@ void LLAsyncInventorySkeletonLoader::evaluateChildren(const FetchRequest& reques
655662
mEssentialPending.insert(child_id);
656663
}
657664
enqueueFetch(child_id, child_is_library, child_essential, cached_child_version);
665+
LL_INFOS("AsyncInventory") << "Async skeleton loader enqueued fetch"
666+
<< " cat_id=" << child_id
667+
<< " name=\"" << child->getName() << "\""
668+
<< " essential=" << (child_essential ? "true" : "false")
669+
<< " cache_valid=" << (child_cache_valid ? "true" : "false")
670+
<< " cached_version=" << cached_child_version
671+
<< " current_version=" << current_child_version
672+
<< LL_ENDL;
658673
}
659674
else if (child_essential && child_cache_valid)
660675
{
676+
LL_INFOS("AsyncInventory") << "Async skeleton loader treating essential folder as fetched"
677+
<< " cat_id=" << child_id
678+
<< " name=\"" << child->getName() << "\""
679+
<< " cached_version=" << cached_child_version
680+
<< " current_version=" << current_child_version
681+
<< LL_ENDL;
661682
mFetchedCategories.insert(child_id);
662683
}
663684
}
@@ -698,13 +719,25 @@ void LLAsyncInventorySkeletonLoader::discoverEssentialFolders()
698719
if (cat && isCategoryUpToDate(cat, cached_version))
699720
{
700721
mFetchedCategories.insert(cat_id);
722+
LL_INFOS("AsyncInventory") << "Essential folder up to date from cache"
723+
<< " cat_id=" << cat_id
724+
<< " name=\"" << cat->getName() << "\""
725+
<< " cached_version=" << cached_version
726+
<< " current_version=" << cat->getVersion()
727+
<< " descendents=" << cat->getDescendentCount()
728+
<< LL_ENDL;
701729
continue;
702730
}
703731

704732
if (mFetchedCategories.count(cat_id) == 0 && mQueuedCategories.count(cat_id) == 0 && mActiveFetches.count(cat_id) == 0)
705733
{
706734
enqueueFetch(cat_id, is_library, true, cached_version);
707735
mEssentialPending.insert(cat_id);
736+
LL_INFOS("AsyncInventory") << "Essential folder queued for fetch"
737+
<< " cat_id=" << cat_id
738+
<< " cached_version=" << cached_version
739+
<< " current_version=" << (cat ? cat->getVersion() : LLViewerInventoryCategory::VERSION_UNKNOWN)
740+
<< LL_ENDL;
708741
}
709742
}
710743

@@ -720,11 +753,21 @@ void LLAsyncInventorySkeletonLoader::discoverEssentialFolders()
720753
if (isCategoryUpToDate(cof, cached_version))
721754
{
722755
mFetchedCategories.insert(cof_id);
756+
LL_INFOS("Inventory") << "COF up to date from cache"
757+
<< " cat_id=" << cof_id
758+
<< " name=\"" << (cof ? cof->getName() : std::string("<null>")) << "\""
759+
<< " cached_version=" << cached_version
760+
<< " current_version=" << (cof ? cof->getVersion() : LLViewerInventoryCategory::VERSION_UNKNOWN)
761+
<< LL_ENDL;
723762
}
724763
else
725764
{
726765
enqueueFetch(cof_id, false, true, cached_version);
727766
mEssentialPending.insert(cof_id);
767+
LL_INFOS("Inventory") << "COF queued for fetch"
768+
<< " cached_version=" << cached_version
769+
<< " current_version=" << (cof ? cof->getVersion() : LLViewerInventoryCategory::VERSION_UNKNOWN)
770+
<< LL_ENDL;
728771
}
729772
}
730773
}

0 commit comments

Comments
 (0)