2828
2929#include < typeinfo>
3030#include < random>
31+ #include < thread>
3132
3233#include " llinventorymodel.h"
3334
@@ -82,7 +83,7 @@ const S32 LLInventoryModel::sCurrentInvCacheVersion = 5;
8283bool LLInventoryModel::sFirstTimeInViewer2 = true ;
8384
8485S32 LLInventoryModel::sPendingSystemFolders = 0 ;
85- std::vector<std::thread> LLInventoryModel:: sPendingCacheThreads ;
86+ std::vector<std::thread> sPendingCacheThreads ;
8687
8788// /----------------------------------------------------------------------------
8889// / Local function declarations, constants, enums, and typedefs
@@ -101,45 +102,6 @@ struct InventoryIDPtrLess
101102 }
102103};
103104
104- class LLCanCache : public LLInventoryCollectFunctor
105- {
106- public:
107- LLCanCache (LLInventoryModel* model) : mModel (model) {}
108- virtual ~LLCanCache () {}
109- virtual bool operator ()(LLInventoryCategory* cat, LLInventoryItem* item);
110- protected:
111- LLInventoryModel* mModel ;
112- std::set<LLUUID > mCachedCatIDs ;
113- };
114-
115- bool LLCanCache::operator ()(LLInventoryCategory* cat, LLInventoryItem* item)
116- {
117- bool rv = false ;
118- if (item)
119- {
120- if (mCachedCatIDs .find (item->getParentUUID ()) != mCachedCatIDs .end ())
121- {
122- rv = true ;
123- }
124- }
125- else if (cat)
126- {
127- // HACK: downcast
128- LLViewerInventoryCategory* c = (LLViewerInventoryCategory*)cat;
129- if (c->getVersion () != LLViewerInventoryCategory::VERSION_UNKNOWN )
130- {
131- S32 descendents_server = c->getDescendentCount ();
132- S32 descendents_actual = c->getViewerDescendentCount ();
133- if (descendents_server == descendents_actual)
134- {
135- mCachedCatIDs .insert (c->getUUID ());
136- rv = true ;
137- }
138- }
139- }
140- return rv;
141- }
142-
143105struct InventoryCallbackInfo
144106{
145107 InventoryCallbackInfo (U32 callback, const LLUUID & inv_id) :
@@ -2372,20 +2334,98 @@ void LLInventoryModel::cache(
23722334 LL_PROFILE_ZONE_SCOPED ;
23732335 LL_DEBUGS (LOG_INV ) << " Caching " << parent_folder_id << " for " << agent_id
23742336 << LL_ENDL ;
2337+
23752338 LLViewerInventoryCategory* root_cat = getCategory (parent_folder_id);
2376- if (!root_cat) return ;
2339+ if (!root_cat)
2340+ {
2341+ LL_WARNS (LOG_INV ) << " Root category not found for " << parent_folder_id << LL_ENDL ;
2342+ return ;
2343+ }
2344+
23772345 cat_array_t categories;
23782346 categories.push_back (root_cat);
23792347 item_array_t items;
23802348
2381- LLCanCache can_cache (this );
2382- can_cache (root_cat, NULL );
2383- collectDescendentsIf (
2384- parent_folder_id,
2385- categories,
2386- items,
2387- INCLUDE_TRASH ,
2388- can_cache);
2349+ // Lambda to check if a category should be cached
2350+ // Only cache if it has known version and matching descendent counts
2351+ auto should_cache_category = [](LLViewerInventoryCategory* cat) -> bool {
2352+ if (!cat || cat->getVersion () == LLViewerInventoryCategory::VERSION_UNKNOWN )
2353+ {
2354+ return false ;
2355+ }
2356+ S32 descendents_server = cat->getDescendentCount ();
2357+ S32 descendents_actual = cat->getViewerDescendentCount ();
2358+ return (descendents_server == descendents_actual);
2359+ };
2360+
2361+ // Track which folders we've verified as cacheable descendants
2362+ std::unordered_set<LLUUID > processed_folders;
2363+ processed_folders.insert (parent_folder_id);
2364+
2365+ // First pass: identify all cacheable descendant folders
2366+ // Use pair of (folder_id, should_save_children)
2367+ std::deque<std::pair<LLUUID , bool >> folders_to_check;
2368+ folders_to_check.push_back (std::make_pair (parent_folder_id, should_cache_category (root_cat)));
2369+
2370+ while (!folders_to_check.empty ())
2371+ {
2372+ auto [current_id, save_children] = folders_to_check.front ();
2373+ folders_to_check.pop_front ();
2374+
2375+ if (save_children) // else incorrect count or version
2376+ {
2377+ auto item_it = mParentChildItemTree .find (current_id);
2378+ if (item_it != mParentChildItemTree .end () && item_it->second )
2379+ {
2380+ for (LLViewerInventoryItem* item : *(item_it->second ))
2381+ {
2382+ if (item)
2383+ {
2384+ items.push_back (item);
2385+ }
2386+ }
2387+ }
2388+ }
2389+
2390+ // Get child categories directly from the parent-child tree
2391+ auto cat_it = mParentChildCategoryTree .find (current_id);
2392+ if (cat_it != mParentChildCategoryTree .end () && cat_it->second )
2393+ {
2394+ for (LLViewerInventoryCategory* child_cat : *(cat_it->second ))
2395+ {
2396+ if (!child_cat)
2397+ {
2398+ continue ;
2399+ }
2400+
2401+ // Verify ownership matches (library vs agent inventory)
2402+ if (child_cat->getOwnerID () != root_cat->getOwnerID ())
2403+ {
2404+ LL_WARNS (LOG_INV ) << " Owner mismatch in category tree: expected "
2405+ << root_cat->getOwnerID () << " got "
2406+ << child_cat->getOwnerID () << " for category "
2407+ << child_cat->getName () << LL_ENDL ;
2408+ continue ;
2409+ }
2410+
2411+ const LLUUID & child_id = child_cat->getUUID ();
2412+
2413+ // Only process each folder once
2414+ if (processed_folders.insert (child_id).second )
2415+ {
2416+ if (should_cache_category (child_cat))
2417+ {
2418+ categories.push_back (child_cat);
2419+ folders_to_check.push_back (std::make_pair (child_id, true ));
2420+ }
2421+ else
2422+ {
2423+ folders_to_check.push_back (std::make_pair (child_id, false ));
2424+ }
2425+ }
2426+ }
2427+ }
2428+ }
23892429
23902430 if (categories.empty () && items.empty ())
23912431 {
@@ -2405,7 +2445,12 @@ void LLInventoryModel::cache(
24052445 std::string gzip_filename = getInvCacheAddres (agent_id);
24062446 gzip_filename.append (" .gz" );
24072447
2408- // Launch detached packing thread
2448+ if (sPendingCacheThreads .empty ())
2449+ {
2450+ LL_INFOS (LOG_INV ) << " Inventory cache compression started" << LL_ENDL ;
2451+ }
2452+
2453+ // Launch background packing thread
24092454 // Main thread is the only one modifying sPendingCacheThreads
24102455 sPendingCacheThreads .emplace_back (
24112456 [temp_file, gzip_filename]() {
@@ -2449,9 +2494,7 @@ void LLInventoryModel::waitForPendingCacheWrites()
24492494 }
24502495 }
24512496
2452- F32 wait_time = wait_timer.getElapsedTimeF32 ();
2453- LL_INFOS (LOG_INV ) << " Inventory cache compressions completed in "
2454- << wait_time << " s" << LL_ENDL ;
2497+ LL_INFOS (LOG_INV ) << " Inventory cache compression completed" << LL_ENDL ;
24552498 }
24562499}
24572500
0 commit comments