From 27046fcc14239d36604790c993a90394361ec873 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 21 Nov 2022 13:48:23 +0000 Subject: SL-18629 - moving createNewCategory to AIS3 --- indra/newview/llappearancemgr.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 909f32cd21..ab7adeeedc 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1701,6 +1701,7 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds { parent_id = gInventory.getRootFolderID(); } + // USES UDP PATH LLUUID subfolder_id = gInventory.createNewCategory( parent_id, LLFolderType::FT_NONE, src_cat->getName()); @@ -2725,7 +2726,8 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap { pid = gInventory.getRootFolderID(); } - + + // UDP PATH LLUUID new_cat_id = gInventory.createNewCategory( pid, LLFolderType::FT_NONE, @@ -3994,7 +3996,8 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo func); } else - { + { + // UDP PATH LLUUID folder_id = gInventory.createNewCategory( parent_id, LLFolderType::FT_OUTFIT, -- cgit v1.3 From f6208020f5b27b84aeb9ca258e8dbddce9c49bce Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 22 Nov 2022 15:46:08 +0000 Subject: SL-18629 - use AISAPI for some paths of new category creation --- indra/newview/llaisapi.cpp | 30 +++++++++++++++++++++++++++--- indra/newview/llaisapi.h | 3 ++- indra/newview/llappearancemgr.cpp | 1 + indra/newview/llinventorymodel.cpp | 35 +++++++++-------------------------- 4 files changed, 39 insertions(+), 30 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 005259bcb8..d2c59cfaba 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -100,7 +100,7 @@ void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, c tid.generate(); std::string url = cap + std::string("/category/") + parentId.asString() + "?tid=" + tid.asString(); - LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; + LL_DEBUGS("Inventory") << "url: " << url << " parentID " << parentId << " newInventory " << newInventory << LL_ENDL; // I may be suffering from golden hammer here, but the first part of this bind // is actually a static cast for &HttpCoroutineAdapter::postAndSuspend so that @@ -124,7 +124,7 @@ void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, c (&LLCoreHttpUtil::HttpCoroutineAdapter::postAndSuspend), _1, _2, _3, _4, _5, _6); LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro, - _1, postFn, url, parentId, newInventory, callback, COPYINVENTORY)); + _1, postFn, url, parentId, newInventory, callback, CREATEINVENTORY)); EnqueueAISCommand("CreateInventory", proc); } @@ -478,6 +478,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht LL_WARNS("Inventory") << ll_pretty_print_sd(result) << LL_ENDL; } + LL_DEBUGS("Inventory") << result << LL_ENDL; gInventory.onAISUpdateReceived("AISCommand", result); if (callback && !callback.empty()) @@ -487,9 +488,32 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht if (result.has("category_id") && (type == COPYLIBRARYCATEGORY)) { id = result["category_id"]; + callback(id); } + if (type == CREATEINVENTORY) + { + if (result.has("_created_categories")) + { + LLSD& cats = result["_created_categories"]; + LLSD::array_const_iterator cat_iter; + for (cat_iter = cats.beginArray(); cat_iter != cats.endArray(); ++cat_iter) + { + LLUUID cat_id = *cat_iter; + callback(cat_id); + } + } + if (result.has("_created_items")) + { + LLSD& items = result["_created_items"]; + LLSD::array_const_iterator item_iter; + for (item_iter = items.beginArray(); item_iter != items.endArray(); ++item_iter) + { + LLUUID item_id = *item_iter; + callback(item_id); + } + } + } - callback(id); } } diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 856f3fc180..6e9cc19baa 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -61,7 +61,8 @@ private: PURGEDESCENDENTS, UPDATECATEGORY, UPDATEITEM, - COPYLIBRARYCATEGORY + COPYLIBRARYCATEGORY, + CREATEINVENTORY } COMMAND_TYPE; static const std::string INVENTORY_CAP_NAME; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index ab7adeeedc..4fc09c7739 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3989,6 +3989,7 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo // existence of AIS as an indicator the fix is present. Does // not actually use AIS to create the category. inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel); + LLUUID folder_id = gInventory.createNewCategory( parent_id, LLFolderType::FT_OUTFIT, diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 36797a3f28..a7b3076e52 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -694,38 +694,20 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, LL_WARNS(LOG_INV) << "Creating new system folder, type " << preferred_type << LL_ENDL; } - id.generate(); std::string name = pname; - if(!pname.empty()) - { - name.assign(pname); - } - else + if (pname.empty()) { name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type)); } - LLViewerRegion* viewer_region = gAgent.getRegion(); - std::string url; - if ( viewer_region ) - url = viewer_region->getCapability("CreateInventoryCategory"); - - if (!url.empty() && callback) + if (callback) { - //Let's use the new capability. - - LLSD request, body; - body["folder_id"] = id; - body["parent_id"] = parent_id; - body["type"] = (LLSD::Integer) preferred_type; - body["name"] = name; - - request["message"] = "CreateInventoryCategory"; - request["payload"] = body; - - LL_DEBUGS(LOG_INV) << "Creating category via request: " << ll_pretty_print_sd(request) << LL_ENDL; - LLCoros::instance().launch("LLInventoryModel::createNewCategoryCoro", - boost::bind(&LLInventoryModel::createNewCategoryCoro, this, url, body, callback)); + LLSD new_inventory = LLSD::emptyMap(); + new_inventory["categories"] = LLSD::emptyArray(); + LLViewerInventoryCategory cat(LLUUID::null, parent_id, preferred_type, name, gAgent.getID()); + LLSD cat_sd = cat.asLLSD(); + new_inventory["categories"].append(cat_sd); + AISAPI::CreateInventory(parent_id, new_inventory, callback); return LLUUID::null; } @@ -740,6 +722,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, // assuming instant success. // Add the category to the internal representation + id.generate(); LLPointer cat = new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID()); cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 -- cgit v1.3 From ce5ac93883b71b6abf8cffa35204541e257c6b02 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 24 Jan 2023 20:15:22 +0000 Subject: SL-18629 - various notes on work for D567 --- indra/newview/llappearancemgr.cpp | 7 ++++++- indra/newview/llfloateropenobject.cpp | 2 ++ indra/newview/llinventoryfunctions.cpp | 1 + indra/newview/llinventorymodel.cpp | 37 +++++++++++++++++++++++++++++++++- 4 files changed, 45 insertions(+), 2 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4fc09c7739..d05c30d722 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1702,6 +1702,7 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds parent_id = gInventory.getRootFolderID(); } // USES UDP PATH + // D567 needs to carry over thumbnail info LLUUID subfolder_id = gInventory.createNewCategory( parent_id, LLFolderType::FT_NONE, src_cat->getName()); @@ -2728,6 +2729,7 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap } // UDP PATH + // D567 needs to carry over thumbnail info if present LLUUID new_cat_id = gInventory.createNewCategory( pid, LLFolderType::FT_NONE, @@ -3983,6 +3985,7 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo // First, make a folder in the My Outfits directory. const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + // D567 replace with coros if (AISAPI::isAvailable()) { // cap-based category creation was buggy until recently. use @@ -3990,6 +3993,7 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo // not actually use AIS to create the category. inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel); + // D567 copy thumbnail info from source folder LLUUID folder_id = gInventory.createNewCategory( parent_id, LLFolderType::FT_OUTFIT, @@ -3998,7 +4002,8 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo } else { - // UDP PATH + // UDP PATH, should remove + // D567 copy thumbnail info from source folder LLUUID folder_id = gInventory.createNewCategory( parent_id, LLFolderType::FT_OUTFIT, diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 2a1749bd42..cff42f72b7 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -166,6 +166,7 @@ void LLFloaterOpenObject::moveToInventory(bool wear, bool replace) } inventory_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear,replace); + // D567 copy thumbnail info LLUUID category_id = gInventory.createNewCategory(parent_category_id, LLFolderType::FT_NONE, name, @@ -173,6 +174,7 @@ void LLFloaterOpenObject::moveToInventory(bool wear, bool replace) //If we get a null category ID, we are using a capability in createNewCategory and we will //handle the following in the callbackCreateInventoryCategory routine. + // D567 review if ( category_id.notNull() ) { LLCatAndWear* data = new LLCatAndWear; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 27edc8148e..145cdf6476 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -403,6 +403,7 @@ void copy_inventory_category(LLInventoryModel* model, bool move_no_copy_items ) { // Create the initial folder + // D567 needs to handle new fields inventory_func_type func = boost::bind(©_inventory_category_content, _1, model, cat, root_copy_id, move_no_copy_items); gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func); } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index a7b3076e52..b64dd431db 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -700,8 +700,13 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type)); } +#ifdef USE_AIS_FOR_NC + // D567 currently this doesn't really work due to limitations in + // AIS3, also violates the common caller assumption that we can + // assign the id and return immediately. if (callback) { + // D567 note that we no longer assign the UUID in the viewer, so various workflows need to change. LLSD new_inventory = LLSD::emptyMap(); new_inventory["categories"] = LLSD::emptyArray(); LLViewerInventoryCategory cat(LLUUID::null, parent_id, preferred_type, name, gAgent.getID()); @@ -711,17 +716,47 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, return LLUUID::null; } +#else + LLViewerRegion* viewer_region = gAgent.getRegion(); + std::string url; + if ( viewer_region ) + url = viewer_region->getCapability("CreateInventoryCategory"); + + if (!url.empty() && callback) + { + //Let's use the new capability. + + id.generate(); + LLSD request, body; + body["folder_id"] = id; + body["parent_id"] = parent_id; + body["type"] = (LLSD::Integer) preferred_type; + body["name"] = name; + + request["message"] = "CreateInventoryCategory"; + request["payload"] = body; + + LL_DEBUGS(LOG_INV) << "Creating category via request: " << ll_pretty_print_sd(request) << LL_ENDL; + LLCoros::instance().launch("LLInventoryModel::createNewCategoryCoro", + boost::bind(&LLInventoryModel::createNewCategoryCoro, this, url, body, callback)); + + return LLUUID::null; + } +#endif + if (!gMessageSystem) { return LLUUID::null; } - // FIXME this UDP code path needs to be removed. Requires + // D567 FIXME this UDP code path needs to be removed. Requires // reworking many of the callers to use callbacks rather than // assuming instant success. // Add the category to the internal representation + LL_WARNS() << "D567 need to remove this usage" << LL_ENDL; + id.generate(); LLPointer cat = new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID()); -- cgit v1.3 From a777a0b27ed6adfa99d708e289e704915f2b62b7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 7 Mar 2023 21:51:14 +0200 Subject: SL-18629 WIP Replacing UDP creation messages with callback based AIS --- indra/newview/llappearancemgr.cpp | 56 +++++++++++-------- indra/newview/llfloatermarketplacelistings.cpp | 35 ++++++++---- indra/newview/llfloateropenobject.cpp | 34 ++---------- indra/newview/llfriendcard.cpp | 41 +++++++++----- indra/newview/llinventoryfunctions.cpp | 60 +++++++++------------ indra/newview/llviewerinventory.cpp | 18 +++++-- indra/newview/llviewermessage.cpp | 75 ++++++++++++++------------ 7 files changed, 173 insertions(+), 146 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index d8e239822e..5595a92b43 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1703,12 +1703,17 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds } // USES UDP PATH // D567 needs to carry over thumbnail info - LLUUID subfolder_id = gInventory.createNewCategory( parent_id, - LLFolderType::FT_NONE, - src_cat->getName()); - shallowCopyCategoryContents(src_id, subfolder_id, cb); + gInventory.createNewCategory( + parent_id, + LLFolderType::FT_NONE, + src_cat->getName(), + [src_id, cb](const LLUUID &new_id) + { + LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_id, new_id, cb); - gInventory.notifyObservers(); + gInventory.notifyObservers(); + } + ); } void LLAppearanceMgr::slamCategoryLinks(const LLUUID& src_id, const LLUUID& dst_id, @@ -2730,21 +2735,27 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap // UDP PATH // D567 needs to carry over thumbnail info if present - LLUUID new_cat_id = gInventory.createNewCategory( + gInventory.createNewCategory( pid, LLFolderType::FT_NONE, - name); - - // Create a CopyMgr that will copy items, manage its own destruction - new LLCallAfterInventoryCopyMgr( - *items, new_cat_id, std::string("wear_inventory_category_callback"), - boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar, - LLAppearanceMgr::getInstance(), - gInventory.getCategory(new_cat_id), - append)); - - // BAP fixes a lag in display of created dir. - gInventory.notifyObservers(); + name, + [cat_id, append](const LLUUID& new_cat_id) + { + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(cat_id, cats, items); + // Create a CopyMgr that will copy items, manage its own destruction + new LLCallAfterInventoryCopyMgr( + *items, new_cat_id, std::string("wear_inventory_category_callback"), + boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar, + LLAppearanceMgr::getInstance(), + gInventory.getCategory(new_cat_id), + append)); + + // BAP fixes a lag in display of created dir. + gInventory.notifyObservers(); + } + ); } else { @@ -4004,11 +4015,14 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo { // UDP PATH, should remove // D567 copy thumbnail info from source folder - LLUUID folder_id = gInventory.createNewCategory( + gInventory.createNewCategory( parent_id, LLFolderType::FT_OUTFIT, - new_folder_name); - onOutfitFolderCreated(folder_id, show_panel); + new_folder_name, + [show_panel](const LLUUID &new_cat_id) + { + LLAppearanceMgr::getInstance()->onOutfitFolderCreated(new_cat_id, show_panel); + }); } } diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp index 58bd4bc82b..88fff58fc8 100644 --- a/indra/newview/llfloatermarketplacelistings.cpp +++ b/indra/newview/llfloatermarketplacelistings.cpp @@ -230,18 +230,31 @@ void LLPanelMarketplaceListings::onTabChange() void LLPanelMarketplaceListings::onAddButtonClicked() { - // Find active panel - LLInventoryPanel* panel = (LLInventoryPanel*)getChild("marketplace_filter_tabs")->getCurrentPanel(); - if (panel) - { - LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); - llassert(marketplacelistings_id.notNull()); - LLFolderType::EType preferred_type = LLFolderType::lookup("category"); - LLUUID category = gInventory.createNewCategory(marketplacelistings_id, preferred_type, LLStringUtil::null); - gInventory.notifyObservers(); - panel->setSelectionByID(category, TRUE); - panel->getRootFolder()->setNeedsAutoRename(TRUE); + LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + llassert(marketplacelistings_id.notNull()); + LLFolderType::EType preferred_type = LLFolderType::lookup("category"); + LLHandle handle = getHandle(); + gInventory.createNewCategory( + marketplacelistings_id, + preferred_type, + LLStringUtil::null, + [handle](const LLUUID &new_cat_id) + { + // Find active panel + LLPanel *marketplace_panel = handle.get(); + if (!marketplace_panel) + { + return; + } + LLInventoryPanel* panel = (LLInventoryPanel*)marketplace_panel->getChild("marketplace_filter_tabs")->getCurrentPanel(); + if (panel) + { + gInventory.notifyObservers(); + panel->setSelectionByID(new_cat_id, TRUE); + panel->getRootFolder()->setNeedsAutoRename(TRUE); + } } + ); } void LLPanelMarketplaceListings::onAuditButtonClicked() diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 12ad6dcd33..73eaced562 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -165,35 +165,11 @@ void LLFloaterOpenObject::moveToInventory(bool wear, bool replace) inventory_func_type func = boost::bind(LLFloaterOpenObject::callbackCreateInventoryCategory,_1,object_id,wear,replace); // D567 copy thumbnail info - LLUUID category_id = gInventory.createNewCategory(parent_category_id, - LLFolderType::FT_NONE, - name, - func); - - //If we get a null category ID, we are using a capability in createNewCategory and we will - //handle the following in the callbackCreateInventoryCategory routine. - // D567 review - if ( category_id.notNull() ) - { - LLCatAndWear* data = new LLCatAndWear; - data->mCatID = category_id; - data->mWear = wear; - data->mFolderResponded = false; - data->mReplace = replace; - - // Copy and/or move the items into the newly created folder. - // Ignore any "you're going to break this item" messages. - BOOL success = move_inv_category_world_to_agent(object_id, category_id, TRUE, - callbackMoveInventory, - (void*)data); - if (!success) - { - delete data; - data = NULL; - - LLNotificationsUtil::add("OpenObjectCannotCopy"); - } - } + gInventory.createNewCategory( + parent_category_id, + LLFolderType::FT_NONE, + name, + func); } // static diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp index e395da7f1e..ce28915d93 100644 --- a/indra/newview/llfriendcard.cpp +++ b/indra/newview/llfriendcard.cpp @@ -478,14 +478,24 @@ void LLFriendCardsManager::ensureFriendsFolderExists() LL_WARNS() << "Failed to find \"" << cat_name << "\" category descendents in Category Tree." << LL_ENDL; } - friends_folder_ID = gInventory.createNewCategory(calling_cards_folder_ID, - LLFolderType::FT_CALLINGCARD, get_friend_folder_name()); - - gInventory.createNewCategory(friends_folder_ID, - LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name()); - - // Now when we have all needed folders we can sync their contents with buddies list. - syncFriendsFolder(); + gInventory.createNewCategory( + calling_cards_folder_ID, + LLFolderType::FT_CALLINGCARD, + get_friend_folder_name(), + [](const LLUUID &new_category_id) + { + gInventory.createNewCategory( + new_category_id, + LLFolderType::FT_CALLINGCARD, + get_friend_all_subfolder_name(), + [](const LLUUID &new_category_id) + { + // Now when we have all needed folders we can sync their contents with buddies list. + LLFriendCardsManager::getInstance()->syncFriendsFolder(); + } + ); + } + ); } } @@ -510,11 +520,16 @@ void LLFriendCardsManager::ensureFriendsAllFolderExists() LL_WARNS() << "Failed to find \"" << cat_name << "\" category descendents in Category Tree." << LL_ENDL; } - friends_all_folder_ID = gInventory.createNewCategory(friends_folder_ID, - LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name()); - - // Now when we have all needed folders we can sync their contents with buddies list. - syncFriendsFolder(); + gInventory.createNewCategory( + friends_folder_ID, + LLFolderType::FT_CALLINGCARD, + get_friend_all_subfolder_name(), + [](const LLUUID &new_cat_id) + { + // Now when we have all needed folders we can sync their contents with buddies list. + LLFriendCardsManager::getInstance()->syncFriendsFolder(); + } + ); } } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index eaea1ef972..79d222d904 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -861,22 +861,6 @@ void open_marketplace_listings() LLFloaterReg::showInstance("marketplace_listings"); } -// Create a new folder in destFolderId with the same name as the item name and return the uuid of the new folder -// Note: this is used locally in various situation where we need to wrap an item into a special folder -LLUUID create_folder_for_item(LLInventoryItem* item, const LLUUID& destFolderId) -{ - llassert(item); - llassert(destFolderId.notNull()); - - LLUUID created_folder_id = gInventory.createNewCategory(destFolderId, LLFolderType::FT_NONE, item->getName()); - gInventory.notifyObservers(); - - // *TODO : Create different notifications for the various cases - LLNotificationsUtil::add("OutboxFolderCreated"); - - return created_folder_id; -} - ///---------------------------------------------------------------------------- // Marketplace functions // @@ -1753,28 +1737,36 @@ bool validate_marketplacelistings( } cb(message,depth,LLError::LEVEL_WARN); } - LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, new_folder_type, folder_name); - - // Move each item to the new folder - while (!items_vector_it->second.empty()) + std::vector &uuid_vector = items_vector_it->second; + gInventory.createNewCategory( + parent_uuid, + new_folder_type, + folder_name, + [uuid_vector, cb, indent, depth, parent_uuid, notify_observers](const LLUUID &new_category_id) { - LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(items_vector_it->second.back()); - if (cb) + // Move each item to the new folder + std::vector::reverse_iterator iter = uuid_vector.rbegin(); + while (iter != uuid_vector.rend()) { - std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Move"); - cb(message,depth,LLError::LEVEL_WARN); + LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(*iter); + if (cb) + { + std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Move"); + cb(message, depth, LLError::LEVEL_WARN); + } + gInventory.changeItemParent(viewer_inv_item, new_category_id, true); + iter++; + } + + // Next type + update_marketplace_category(parent_uuid); + update_marketplace_category(new_category_id); + if (notify_observers) + { + gInventory.notifyObservers(); } - gInventory.changeItemParent(viewer_inv_item, folder_uuid, true); - items_vector_it->second.pop_back(); - } - - // Next type - update_marketplace_category(parent_uuid); - update_marketplace_category(folder_uuid); - if (notify_observers) - { - gInventory.notifyObservers(); } + ); items_vector_it++; } } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 27f57bda81..d0832e16d7 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1696,9 +1696,21 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge, parent_id = gInventory.getRootFolderID(); } - LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null); - gInventory.notifyObservers(); - panel->setSelectionByID(category, TRUE); + LLHandle handle = panel->getHandle(); + gInventory.createNewCategory( + parent_id, + preferred_type, + LLStringUtil::null, + [handle](const LLUUID &new_category_id) + { + gInventory.notifyObservers(); + LLInventoryPanel* panel = static_cast(handle.get()); + if (panel) + { + panel->setSelectionByID(new_category_id, TRUE); + } + } + ); } else if ("lsl" == type_name) { diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 5266db5b38..767e092318 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5898,42 +5898,47 @@ void container_inventory_arrived(LLViewerObject* object, { // create a new inventory category to put this in LLUUID cat_id; - cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(), - LLFolderType::FT_NONE, - LLTrans::getString("AcquiredItems")); + gInventory.createNewCategory( + gInventory.getRootFolderID(), + LLFolderType::FT_NONE, + LLTrans::getString("AcquiredItems"), + [inventory](const LLUUID &new_cat_id) + { + LLInventoryObject::object_list_t::const_iterator it = inventory->begin(); + LLInventoryObject::object_list_t::const_iterator end = inventory->end(); + for (; it != end; ++it) + { + if ((*it)->getType() != LLAssetType::AT_CATEGORY) + { + LLInventoryObject* obj = (LLInventoryObject*)(*it); + LLInventoryItem* item = (LLInventoryItem*)(obj); + LLUUID item_id; + item_id.generate(); + time_t creation_date_utc = time_corrected(); + LLPointer new_item + = new LLViewerInventoryItem(item_id, + new_cat_id, + item->getPermissions(), + item->getAssetUUID(), + item->getType(), + item->getInventoryType(), + item->getName(), + item->getDescription(), + LLSaleInfo::DEFAULT, + item->getFlags(), + creation_date_utc); + new_item->updateServer(TRUE); + gInventory.updateItem(new_item); + } + } + gInventory.notifyObservers(); - LLInventoryObject::object_list_t::const_iterator it = inventory->begin(); - LLInventoryObject::object_list_t::const_iterator end = inventory->end(); - for ( ; it != end; ++it) - { - if ((*it)->getType() != LLAssetType::AT_CATEGORY) - { - LLInventoryObject* obj = (LLInventoryObject*)(*it); - LLInventoryItem* item = (LLInventoryItem*)(obj); - LLUUID item_id; - item_id.generate(); - time_t creation_date_utc = time_corrected(); - LLPointer new_item - = new LLViewerInventoryItem(item_id, - cat_id, - item->getPermissions(), - item->getAssetUUID(), - item->getType(), - item->getInventoryType(), - item->getName(), - item->getDescription(), - LLSaleInfo::DEFAULT, - item->getFlags(), - creation_date_utc); - new_item->updateServer(TRUE); - gInventory.updateItem(new_item); - } - } - gInventory.notifyObservers(); - if(active_panel) - { - active_panel->setSelection(cat_id, TAKE_FOCUS_NO); - } + LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(); + if (active_panel) + { + active_panel->setSelection(new_cat_id, TAKE_FOCUS_NO); + } + }); } else if (inventory->size() == 2) { -- cgit v1.3 From 811da7dbb1bdbf04a2dceb02ad4d296db4274076 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 7 Mar 2023 22:39:36 +0200 Subject: SL-18629 WIP Replacing UDP creation messages with callback based AIS #2 findCategory and move_item_to_marketplacelistings --- indra/newview/llappearancemgr.cpp | 2 +- indra/newview/llfloatereditenvironmentbase.cpp | 2 +- indra/newview/llfloatergesture.cpp | 2 +- indra/newview/llfloaterlinkreplace.cpp | 4 +- indra/newview/llfloatermarketplacelistings.cpp | 49 ++++++++--- indra/newview/llfloatermarketplacelistings.h | 1 + indra/newview/llinventorybridge.cpp | 66 +++++++-------- indra/newview/llinventoryfunctions.cpp | 102 ++++++++++++----------- indra/newview/llinventorymodel.cpp | 107 ++++++++++++++++++------- indra/newview/llinventorymodel.h | 15 ++-- indra/newview/llinventorypanel.cpp | 2 +- indra/newview/llmarketplacefunctions.cpp | 4 +- indra/newview/llpaneloutfitsinventory.cpp | 2 +- indra/newview/llsidepanelinventory.cpp | 2 +- indra/newview/llstartup.cpp | 2 +- indra/newview/lltooldraganddrop.cpp | 6 +- indra/newview/llviewermenu.cpp | 4 +- 17 files changed, 233 insertions(+), 139 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5595a92b43..1c55113082 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3213,7 +3213,7 @@ void LLAppearanceMgr::copyLibraryGestures() // Copy gestures LLUUID lib_gesture_cat_id = - gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_GESTURE,false); + gInventory.findLibraryCategoryUUIDForType(LLFolderType::FT_GESTURE); if (lib_gesture_cat_id.isNull()) { LL_WARNS() << "Unable to copy gestures, source category not found" << LL_ENDL; diff --git a/indra/newview/llfloatereditenvironmentbase.cpp b/indra/newview/llfloatereditenvironmentbase.cpp index 2850951668..cd24d79b7f 100644 --- a/indra/newview/llfloatereditenvironmentbase.cpp +++ b/indra/newview/llfloatereditenvironmentbase.cpp @@ -260,7 +260,7 @@ void LLFloaterEditEnvironmentBase::onSaveAsCommit(const LLSD& notification, cons } else if (mInventoryItem) { - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); LLUUID parent_id = mInventoryItem->getParentUUID(); if (marketplacelistings_id == parent_id || gInventory.isObjectDescendentOf(mInventoryItem->getUUID(), gInventory.getLibraryRootFolderID())) { diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index d17889bed1..f29046c513 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -211,7 +211,7 @@ BOOL LLFloaterGesture::postBuild() getChildView("play_btn")->setVisible( true); getChildView("stop_btn")->setVisible( false); setDefaultBtn("play_btn"); - mGestureFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE, false); + mGestureFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE); uuid_vec_t folders; folders.push_back(mGestureFolderID); diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp index 8ee7a72055..b42c49c607 100644 --- a/indra/newview/llfloaterlinkreplace.cpp +++ b/indra/newview/llfloaterlinkreplace.cpp @@ -335,8 +335,8 @@ BOOL LLFloaterLinkReplace::tick() void LLFloaterLinkReplace::processBatch(LLInventoryModel::item_array_t items) { const LLViewerInventoryItem* target_item = gInventory.getItem(mTargetUUID); - const LLUUID cof_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const LLUUID outfit_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + const LLUUID cof_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID outfit_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); for (LLInventoryModel::item_array_t::iterator it = items.begin(); it != items.end(); ++it) { diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp index 88fff58fc8..9110d9e902 100644 --- a/indra/newview/llfloatermarketplacelistings.cpp +++ b/indra/newview/llfloatermarketplacelistings.cpp @@ -230,7 +230,7 @@ void LLPanelMarketplaceListings::onTabChange() void LLPanelMarketplaceListings::onAddButtonClicked() { - LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); llassert(marketplacelistings_id.notNull()); LLFolderType::EType preferred_type = LLFolderType::lookup("category"); LLHandle handle = getHandle(); @@ -375,6 +375,7 @@ LLFloaterMarketplaceListings::LLFloaterMarketplaceListings(const LLSD& key) , mInventoryTitle(NULL) , mPanelListings(NULL) , mPanelListingsSet(false) +, mRootFolderCreating(false) { } @@ -460,15 +461,39 @@ void LLFloaterMarketplaceListings::setRootFolder() // If we are *not* a merchant or we have no market place connection established yet, do nothing return; } + if (!gInventory.isInventoryUsable()) + { + return; + } + LLFolderType::EType preferred_type = LLFolderType::FT_MARKETPLACE_LISTINGS; // We are a merchant. Get the Marketplace listings folder, create it if needs be. - LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, true); - if (marketplacelistings_id.isNull()) - { - // We should never get there unless the inventory fails badly - LL_ERRS("SLM") << "Inventory problem: failure to create the marketplace listings folder for a merchant!" << LL_ENDL; - return; - } + LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(preferred_type); + + if (marketplacelistings_id.isNull()) + { + if (!mRootFolderCreating) + { + mRootFolderCreating = true; + gInventory.createNewCategory( + gInventory.getRootFolderID(), + preferred_type, + LLStringUtil::null, + [preferred_type](const LLUUID &new_cat_id) + { + LLFloaterMarketplaceListings *marketplace = LLFloaterReg::findTypedInstance("marketplace_listings"); + if (marketplace) + { + // will call setRootFolder again + marketplace->updateView(); + } + } + ); + } + return; + } + + mRootFolderCreating = false; // No longer need to observe new category creation if (mCategoryAddedObserver && gInventory.containsObserver(mCategoryAddedObserver)) @@ -486,6 +511,7 @@ void LLFloaterMarketplaceListings::setRootFolder() } mRootFolderId = marketplacelistings_id; + mRootFolderCreating = true; } void LLFloaterMarketplaceListings::setPanels() @@ -556,6 +582,11 @@ void LLFloaterMarketplaceListings::updateView() { setRootFolder(); } + if (mRootFolderCreating) + { + // waiting for callback + return; + } // Update the bottom initializing status and progress dial if we are initializing or if we're a merchant and still loading if ((mkt_status <= MarketplaceStatusCodes::MARKET_PLACE_INITIALIZING) || (is_merchant && (data_fetched <= MarketplaceFetchCodes::MARKET_FETCH_LOADING)) ) @@ -859,7 +890,7 @@ void LLFloaterMarketplaceValidation::onOpen(const LLSD& key) LLUUID cat_id(key.asUUID()); if (cat_id.isNull()) { - cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + cat_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); } // Validates the folder diff --git a/indra/newview/llfloatermarketplacelistings.h b/indra/newview/llfloatermarketplacelistings.h index 77e855fd2a..085e517a9d 100644 --- a/indra/newview/llfloatermarketplacelistings.h +++ b/indra/newview/llfloatermarketplacelistings.h @@ -140,6 +140,7 @@ private: LLTextBox * mInventoryTitle; LLUUID mRootFolderId; + bool mRootFolderCreating; LLPanelMarketplaceListings * mPanelListings; bool mPanelListingsSet; }; diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 0c7f237415..fb92437c3d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -333,7 +333,7 @@ BOOL LLInvFVBridge::cutToClipboard() const LLInventoryObject* obj = gInventory.getObject(mUUID); if (obj && isItemMovable() && isItemRemovable()) { - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); const BOOL cut_from_marketplacelistings = gInventory.isObjectDescendentOf(mUUID, marketplacelistings_id); if (cut_from_marketplacelistings && (LLMarketplaceData::instance().isInActiveFolder(mUUID) || @@ -1286,7 +1286,7 @@ bool LLInvFVBridge::isItemInOutfits() const const LLInventoryModel* model = getInventoryModel(); if(!model) return false; - const LLUUID my_outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + const LLUUID my_outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); return isCOFFolder() || (my_outfits_cat == mUUID) || model->isObjectDescendentOf(mUUID, my_outfits_cat); } @@ -1321,7 +1321,7 @@ BOOL LLInvFVBridge::isCOFFolder() const // *TODO : Suppress isInboxFolder() once Merchant Outbox is fully deprecated BOOL LLInvFVBridge::isInboxFolder() const { - const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false); + const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); if (inbox_id.isNull()) { @@ -1333,7 +1333,7 @@ BOOL LLInvFVBridge::isInboxFolder() const BOOL LLInvFVBridge::isMarketplaceListingsFolder() const { - const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (folder_id.isNull()) { @@ -1633,7 +1633,7 @@ bool LLInvFVBridge::canListOnMarketplaceNow() const { std::string error_msg; LLInventoryModel* model = getInventoryModel(); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (marketplacelistings_id.notNull()) { LLViewerInventoryCategory * master_folder = model->getCategory(marketplacelistings_id); @@ -1792,7 +1792,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) { LLInventoryItem* itemp = model->getItem(mUUID); if (!itemp) return; - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); // Note: For a single item, if it's not a copy, then it's a move move_item_to_marketplacelistings(itemp, marketplacelistings_id, ("copy_to_marketplace_listings" == action)); } @@ -2566,8 +2566,8 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, if (!filter) return false; const LLUUID &cat_id = inv_cat->getUUID(); - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); const LLUUID from_folder_uuid = inv_cat->getParentUUID(); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); @@ -2585,10 +2585,10 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, if (is_agent_inventory) { - const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); - const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); - const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); - const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND, false); + const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); + const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); + const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); @@ -2871,7 +2871,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, } else { - if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX, false))) + if (model->isObjectDescendentOf(cat_id, model->findCategoryUUIDForType(LLFolderType::FT_INBOX))) { set_dad_inbox_object(cat_id); } @@ -3490,7 +3490,7 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) { LLInventoryCategory * cat = gInventory.getCategory(mUUID); if (!cat) return; - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); move_folder_to_marketplacelistings(cat, marketplacelistings_id, ("move_to_marketplace_listings" != action), (("copy_or_move_to_marketplace_listings" == action))); } } @@ -3740,7 +3740,7 @@ void LLFolderBridge::pasteFromClipboard() LLInventoryModel* model = getInventoryModel(); if (model && isClipboardPasteable()) { - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); const BOOL paste_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id); BOOL cut_from_marketplacelistings = FALSE; @@ -3801,11 +3801,11 @@ void LLFolderBridge::perform_pasteFromClipboard() LLInventoryModel* model = getInventoryModel(); if (model && isClipboardPasteable()) { - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); - const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); - const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); - const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND, false); + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); @@ -4053,9 +4053,9 @@ void LLFolderBridge::pasteLinkFromClipboard() LLInventoryModel* model = getInventoryModel(); if(model) { - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); - const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); const BOOL move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id); @@ -4125,8 +4125,8 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); const LLUUID &lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND); const LLUUID &favorites = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); - const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); - const LLUUID &outfits_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + const LLUUID &marketplace_listings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &outfits_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); if (outfits_id == mUUID) { @@ -4977,7 +4977,7 @@ void LLFolderBridge::dropToOutfit(LLInventoryItem* inv_item, BOOL move_is_into_c { if((inv_item->getInventoryType() == LLInventoryType::IT_TEXTURE) || (inv_item->getInventoryType() == LLInventoryType::IT_SNAPSHOT)) { - const LLUUID &my_outifts_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + const LLUUID &my_outifts_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); if(mUUID != my_outifts_id) { LLFloaterOutfitPhotoPreview* photo_preview = LLFloaterReg::showTypedInstance("outfit_photo_preview", inv_item->getUUID()); @@ -5093,11 +5093,11 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLInventoryFilter* filter = getInventoryFilter(); if (!filter) return false; - const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); - const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false); - const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); - const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); - const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE); + const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK); + const LLUUID &marketplacelistings_id = model->findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + const LLUUID &my_outifts_id = model->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); const LLUUID from_folder_uuid = inv_item->getParentUUID(); const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id); @@ -5117,7 +5117,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLViewerObject* object = NULL; if(LLToolDragAndDrop::SOURCE_AGENT == source) { - const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); + const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH); const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); const BOOL move_is_outof_current_outfit = LLAppearanceMgr::instance().getIsInCOF(inv_item->getUUID()); @@ -5278,7 +5278,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, else { // set up observer to select item once drag and drop from inbox is complete - if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, false))) + if (gInventory.isObjectDescendentOf(inv_item->getUUID(), gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX))) { set_dad_inbox_object(inv_item->getUUID()); } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 79d222d904..6b406c4c9c 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -372,7 +372,7 @@ void update_all_marketplace_count(const LLUUID& cat_id) void update_all_marketplace_count() { // Get the marketplace root and launch the recursive exploration - const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (!marketplace_listings_uuid.isNull()) { update_all_marketplace_count(marketplace_listings_uuid); @@ -875,7 +875,7 @@ S32 depth_nesting_in_marketplace(LLUUID cur_uuid) // Todo: findCategoryUUIDForType is somewhat expensive with large // flat root folders yet we use depth_nesting_in_marketplace at // every turn, find a way to correctly cache this id. - const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (marketplace_listings_uuid.isNull()) { return -1; @@ -1347,6 +1347,7 @@ bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLIn return accept; } +// Can happen asynhroneously!!! bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy) { // Get the marketplace listings depth of the destination folder, exit with error if not under marketplace @@ -1386,53 +1387,64 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol if (can_move_to_marketplace(inv_item, error_msg, true)) { // When moving an isolated item, we might need to create the folder structure to support it + + LLUUID item_id = inv_item->getUUID(); + std::function callback_create_stock = [copy, item_id](const LLUUID& new_cat_id) + { + // Verify we can have this item in that destination category + LLViewerInventoryCategory* dest_cat = gInventory.getCategory(new_cat_id); + LLViewerInventoryItem * viewer_inv_item = gInventory.getItem(item_id); + if (!dest_cat->acceptItem(viewer_inv_item)) + { + LLSD subs; + subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Accepted"); + LLNotificationsUtil::add("MerchantPasteFailed", subs); + } + + if (copy) + { + // Copy the item + LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, new_cat_id)); + copy_inventory_item( + gAgent.getID(), + viewer_inv_item->getPermissions().getOwner(), + viewer_inv_item->getUUID(), + new_cat_id, + std::string(), + cb); + } + else + { + // Reparent the item + gInventory.changeItemParent(viewer_inv_item, new_cat_id, true); + } + }; + + std::function callback_dest_create = [copy, item_id, callback_create_stock](const LLUUID& new_cat_id) + { + LLViewerInventoryCategory* dest_cat = gInventory.getCategory(new_cat_id); + LLViewerInventoryItem * viewer_inv_item = gInventory.getItem(item_id); + if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) && + (dest_cat->getPreferredType() != LLFolderType::FT_MARKETPLACE_STOCK)) + { + // We need to create a stock folder to move a no copy item + gInventory.createNewCategory(new_cat_id, LLFolderType::FT_MARKETPLACE_STOCK, viewer_inv_item->getName(), callback_create_stock); + } + else + { + callback_create_stock(new_cat_id); + } + }; + if (depth == 0) { // We need a listing folder - dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName()); - depth++; + gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName(), callback_dest_create); } if (depth == 1) { // We need a version folder - dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName()); - depth++; - } - LLViewerInventoryCategory* dest_cat = gInventory.getCategory(dest_folder); - if (!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) && - (dest_cat->getPreferredType() != LLFolderType::FT_MARKETPLACE_STOCK)) - { - // We need to create a stock folder to move a no copy item - dest_folder = gInventory.createNewCategory(dest_folder, LLFolderType::FT_MARKETPLACE_STOCK, viewer_inv_item->getName()); - dest_cat = gInventory.getCategory(dest_folder); - depth++; - } - - // Verify we can have this item in that destination category - if (!dest_cat->acceptItem(viewer_inv_item)) - { - LLSD subs; - subs["[ERROR_CODE]"] = LLTrans::getString("Marketplace Error Prefix") + LLTrans::getString("Marketplace Error Not Accepted"); - LLNotificationsUtil::add("MerchantPasteFailed", subs); - return false; - } - - if (copy) - { - // Copy the item - LLPointer cb = new LLBoostFuncInventoryCallback(boost::bind(update_folder_cb, dest_folder)); - copy_inventory_item( - gAgent.getID(), - viewer_inv_item->getPermissions().getOwner(), - viewer_inv_item->getUUID(), - dest_folder, - std::string(), - cb); - } - else - { - // Reparent the item - gInventory.changeItemParent(viewer_inv_item, dest_folder, true); + gInventory.createNewCategory(dest_folder, LLFolderType::FT_NONE, viewer_inv_item->getName(), callback_dest_create); } } else @@ -2496,7 +2508,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if ("delete" == action) { static bool sDisplayedAtSession = false; - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); bool marketplacelistings_item = false; LLAllDescendentsPassedFilter f; for (std::set::iterator it = selected_items.begin(); (it != selected_items.end()) && (f.allDescendentsPassedFilter()); ++it) @@ -2620,7 +2632,7 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root if (action == "wear" || action == "wear_add") { const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); - const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID mp_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); std::copy_if(selected_uuid_set.begin(), selected_uuid_set.end(), std::back_inserter(ids), @@ -2873,7 +2885,7 @@ void LLInventoryAction::buildMarketplaceFolders(LLFolderView* root) // target listing *and* the original listing. So we need to keep track of both. // Note: do not however put the marketplace listings root itself in this list or the whole marketplace data will be rebuilt. sMarketplaceFolders.clear(); - const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID &marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (marketplacelistings_id.isNull()) { return; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index fb19994054..b2cfc8584e 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -804,10 +804,63 @@ void LLInventoryModel::consolidateForType(const LLUUID& main_id, LLFolderType::E } } +void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred_type) +{ + LLUUID rv = LLUUID::null; + LLUUID root_id = gInventory.getRootFolderID(); + if (LLFolderType::FT_ROOT_INVENTORY == preferred_type) + { + rv = root_id; + } + else if (root_id.notNull()) + { + cat_array_t* cats = NULL; + cats = get_ptr_in_map(mParentChildCategoryTree, root_id); + if (cats) + { + S32 count = cats->size(); + for (S32 i = 0; i < count; ++i) + { + LLViewerInventoryCategory* p_cat = cats->at(i); + if (p_cat && p_cat->getPreferredType() == preferred_type) + { + const LLUUID& folder_id = cats->at(i)->getUUID(); + if (rv.isNull() || folder_id < rv) + { + rv = folder_id; + } + } + } + } + } + + if (rv.isNull() && root_id.notNull()) + { + + if (isInventoryUsable()) + { + createNewCategory( + root_id, + preferred_type, + LLStringUtil::null, + [preferred_type](const LLUUID &new_cat_id) + { + LL_DEBUGS("Inventory") << "Created category: " << new_cat_id + << " for type: " << preferred_type << LL_ENDL; + } + ); + } + else + { + LL_WARNS("Inventory") << "Can't create requested folder, type " << preferred_type + << " because inventory is not usable" << LL_ENDL; + } + } +} + const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot( LLFolderType::EType preferred_type, - bool create_folder, - const LLUUID& root_id) + const LLUUID& root_id) const { LLUUID rv = LLUUID::null; if(LLFolderType::FT_ROOT_INVENTORY == preferred_type) @@ -836,18 +889,14 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot( } } - if(rv.isNull() && create_folder && root_id.notNull()) + if(rv.isNull() && root_id.notNull() && preferred_type != LLFolderType::FT_MARKETPLACE_LISTINGS) { - - if (isInventoryUsable()) - { - return createNewCategory(root_id, preferred_type, LLStringUtil::null); - } - else - { - LL_WARNS("Inventory") << "Can't create requested folder, type " << preferred_type - << " because inventory is not usable" << LL_ENDL; - } + // if it does not exists, it should either be added + // to createCommonSystemCategories or server should + // have set it + llassert(false); + LL_WARNS("Inventory") << "Tried to find folder, type " << preferred_type + << " but category does not exist" << LL_ENDL; } return rv; } @@ -856,12 +905,12 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot( // specifies 'type' as what it defaults to containing. The category is // not necessarily only for that type. *NOTE: This will create a new // inventory category on the fly if one does not exist. -const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder) +const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType preferred_type) const { - return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getRootFolderID()); + return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getRootFolderID()); } -const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type) +const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type) const { LLUUID cat_id; switch (preferred_type) @@ -892,14 +941,14 @@ const LLUUID LLInventoryModel::findUserDefinedCategoryUUIDForType(LLFolderType:: if (cat_id.isNull() || !getCategory(cat_id)) { - cat_id = findCategoryUUIDForTypeInRoot(preferred_type, true, getRootFolderID()); + cat_id = findCategoryUUIDForTypeInRoot(preferred_type, getRootFolderID()); } return cat_id; } -const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder) +const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type) const { - return findCategoryUUIDForTypeInRoot(preferred_type, create_folder, gInventory.getLibraryRootFolderID()); + return findCategoryUUIDForTypeInRoot(preferred_type, gInventory.getLibraryRootFolderID()); } // Convenience function to create a new category. You could call @@ -1556,7 +1605,7 @@ void LLInventoryModel::updateCategory(const LLViewerInventoryCategory* cat, U32 mask |= LLInventoryObserver::LABEL; } // Under marketplace, category labels are quite complex and need extra upate - const LLUUID marketplace_id = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID marketplace_id = findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (marketplace_id.notNull() && isObjectDescendentOf(cat->getUUID(), marketplace_id)) { mask |= LLInventoryObserver::LABEL; @@ -2881,7 +2930,7 @@ void LLInventoryModel::buildParentChildMap() } } - const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, FALSE) != LLUUID::null); + const BOOL COF_exists = (findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) != LLUUID::null); sFirstTimeInViewer2 = !COF_exists || gAgent.isFirstLogin(); @@ -3101,14 +3150,14 @@ LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground, void LLInventoryModel::createCommonSystemCategories() { - gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH,true); - gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true); - gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD,true); - gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS,true); - gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, true); - gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, true); // folder should exist before user tries to 'landmark this' - gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS, true); - gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, true); + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_TRASH); + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_FAVORITE); + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CALLINGCARD); + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_MY_OUTFITS); + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT); + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_LANDMARK); // folder should exist before user tries to 'landmark this' + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_SETTINGS); + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_INBOX); } struct LLUUIDAndName diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index b03181d646..1fde5a3b2f 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -303,24 +303,25 @@ public: // Find //-------------------------------------------------------------------- public: + + // Checks if category exists (My Inventory only), if it does not, creates it + void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred_type); + const LLUUID findCategoryUUIDForTypeInRoot( LLFolderType::EType preferred_type, - bool create_folder, - const LLUUID& root_id); + const LLUUID& root_id) const; // Returns the uuid of the category that specifies 'type' as what it // defaults to containing. The category is not necessarily only for that type. // NOTE: If create_folder is true, this will create a new inventory category // on the fly if one does not exist. *NOTE: if find_in_library is true it // will search in the user's library folder instead of "My Inventory" - const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type, - bool create_folder = true); + const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type) const; // will search in the user's library folder instead of "My Inventory" - const LLUUID findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type, - bool create_folder = true); + const LLUUID findLibraryCategoryUUIDForType(LLFolderType::EType preferred_type) const; // Returns user specified category for uploads, returns default id if there are no // user specified one or it does not exist, creates default category if it is missing. - const LLUUID findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type); + const LLUUID findUserDefinedCategoryUUIDForType(LLFolderType::EType preferred_type) const; // Get whatever special folder this object is a child of, if any. const LLViewerInventoryCategory *getFirstNondefaultParent(const LLUUID& obj_id) const; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 037dda70f0..7d4abab98f 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -745,7 +745,7 @@ LLUUID LLInventoryPanel::getRootFolderID() LLStringExplicit label(mParams.start_folder.name()); setLabel(label); - root_id = gInventory.findCategoryUUIDForType(preferred_type, false); + root_id = gInventory.findCategoryUUIDForType(preferred_type); if (root_id.isNull()) { LL_WARNS() << "Could not find folder of type " << preferred_type << LL_ENDL; diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 2d726409c6..5b86f2cc4b 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -897,7 +897,7 @@ void LLMarketplaceData::setDataFetchedSignal(const status_updated_signal_t::slot // Get/Post/Put requests to the SLM Server using the SLM API void LLMarketplaceData::getSLMListings() { - const LLUUID marketplaceFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID marketplaceFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); setUpdating(marketplaceFolderId, true); LLCoros::instance().launch("getSLMListings", @@ -1804,7 +1804,7 @@ bool LLMarketplaceData::isUpdating(const LLUUID& folder_id, S32 depth) } else { - const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID marketplace_listings_uuid = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); std::set::iterator it = mPendingUpdateSet.find(marketplace_listings_uuid); if (it != mPendingUpdateSet.end()) { diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 531073526b..2274937ea5 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -87,7 +87,7 @@ BOOL LLPanelOutfitsInventory::postBuild() // ( This is only necessary if we want to show a warning if a user deletes an item that has a // a link in an outfit, see "ConfirmItemDeleteHasLinks". ) - const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); + const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); if (outfits_cat.notNull()) { LLInventoryModelBackgroundFetch::instance().start(outfits_cat); diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index cfceefed26..de0330588b 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -221,7 +221,7 @@ void LLSidepanelInventory::updateInbox() // // Track inbox folder changes // - const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, true); + const LLUUID inbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX); // Set up observer to listen for creation of inbox if it doesn't exist if (inbox_id.isNull()) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 6883ead5ee..776b9f8279 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2768,7 +2768,7 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, // Not going through the processAgentInitialWearables path, so need to set this here. LLAppearanceMgr::instance().setAttachmentInvLinkEnable(true); // Initiate creation of COF, since we're also bypassing that. - gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CURRENT_OUTFIT); ESex gender; if (gender_name == "male") diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index b16b26b96e..d10b999220 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -764,7 +764,7 @@ void LLToolDragAndDrop::dragOrDrop( S32 x, S32 y, MASK mask, BOOL drop, if (!handled) { // Disallow drag and drop to 3D from the marketplace - const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (marketplacelistings_id.notNull()) { for (S32 item_index = 0; item_index < (S32)mCargoIDs.size(); item_index++) @@ -1732,7 +1732,7 @@ EAcceptance LLToolDragAndDrop::dad3dRezAttachmentFromInv( return ACCEPT_NO; } - const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX); if(gInventory.isObjectDescendentOf(item->getUUID(), outbox_id)) { // Legacy @@ -2159,7 +2159,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory( return ACCEPT_NO; } - const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); + const LLUUID &outbox_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTBOX); if(gInventory.isObjectDescendentOf(category->getUUID(), outbox_id)) { // Legacy diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 015a887e9f..4c51b58474 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -403,14 +403,14 @@ void set_merchant_SLM_menu() LLCommand* command = LLCommandManager::instance().getCommand("marketplacelistings"); gToolBarView->enableCommand(command->id(), true); - const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, false); + const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); if (marketplacelistings_id.isNull()) { U32 mkt_status = LLMarketplaceData::instance().getSLMStatus(); bool is_merchant = (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_MERCHANT) || (mkt_status == MarketplaceStatusCodes::MARKET_PLACE_MIGRATED_MERCHANT); if (is_merchant) { - gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS, true); + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_MARKETPLACE_LISTINGS); LL_WARNS("SLM") << "Creating the marketplace listings folder for a merchant" << LL_ENDL; } } -- cgit v1.3 From da27311473c2c2cc35440f88aa25c9378fc8f4d4 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 10 Mar 2023 23:55:05 +0200 Subject: SL-18629 Creare items via AIS placeholder --- indra/newview/llappearancemgr.cpp | 31 ++++-------------- indra/newview/llviewerinventory.cpp | 64 ++++++++++++++++++++++++++++++++----- 2 files changed, 63 insertions(+), 32 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 1c55113082..4e36a4c351 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3996,34 +3996,17 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo // First, make a folder in the My Outfits directory. const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - // D567 replace with coros - if (AISAPI::isAvailable()) - { - // cap-based category creation was buggy until recently. use - // existence of AIS as an indicator the fix is present. Does - // not actually use AIS to create the category. - inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel); - // D567 copy thumbnail info from source folder - gInventory.createNewCategory( - parent_id, - LLFolderType::FT_OUTFIT, - new_folder_name, - func); - } - else - { - // UDP PATH, should remove - // D567 copy thumbnail info from source folder - gInventory.createNewCategory( - parent_id, - LLFolderType::FT_OUTFIT, - new_folder_name, - [show_panel](const LLUUID &new_cat_id) + // UDP PATH, should remove + // D567 copy thumbnail info from source folder + gInventory.createNewCategory( + parent_id, + LLFolderType::FT_OUTFIT, + new_folder_name, + [show_panel](const LLUUID &new_cat_id) { LLAppearanceMgr::getInstance()->onOutfitFolderCreated(new_cat_id, show_panel); }); - } } void LLAppearanceMgr::wearBaseOutfit() diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d0832e16d7..6f7c5d96f5 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1000,13 +1000,18 @@ void create_notecard_cb(const LLUUID& inv_item) LLInventoryCallbackManager gInventoryCallbacks; -void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, - const LLUUID& parent, const LLTransactionID& transaction_id, - const std::string& name, - const std::string& desc, LLAssetType::EType asset_type, - LLInventoryType::EType inv_type, U8 subtype, - U32 next_owner_perm, - LLPointer cb) +void create_inventory_item( + const LLUUID& agent_id, + const LLUUID& session_id, + const LLUUID& parent_id, + const LLTransactionID& transaction_id, + const std::string& name, + const std::string& desc, + LLAssetType::EType asset_type, + LLInventoryType::EType inv_type, + U8 subtype, + U32 next_owner_perm, + LLPointer cb) { //check if name is equal to one of special inventory items names //EXT-5839 @@ -1027,6 +1032,49 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, } } +#ifdef USE_AIS_FOR_NC + // D567 currently this doesn't work due to missing AIS3 support + if (AISAPI::isAvailable()) + { + LLSD new_inventory = LLSD::emptyMap(); + new_inventory["items"] = LLSD::emptyArray(); + + LLPermissions perms; + perms.init( + gAgentID, + gAgentID, + LLUUID::null, + LLUUID::null); + perms.initMasks( + PERM_ALL, + PERM_ALL, + PERM_NONE, + PERM_NONE, + next_owner_perm); + + LLUUID null_id; + LLPointer item = new LLViewerInventoryItem( + null_id, /*don't know yet*/ + parent_id, + perms, + null_id, /*don't know yet*/ + asset_type, + inv_type, + server_name, + desc, + LLSaleInfo(), + 0, + 0 /*don't know yet, whenever server creates it*/); + LLSD item_sd = item->asLLSD(); + new_inventory["items"].append(item_sd); + AISAPI::CreateInventory( + parent_id, + new_inventory, + nullptr); + return; + } +#endif + LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_CreateInventoryItem); msg->nextBlock(_PREHASH_AgentData); @@ -1034,7 +1082,7 @@ void create_inventory_item(const LLUUID& agent_id, const LLUUID& session_id, msg->addUUIDFast(_PREHASH_SessionID, session_id); msg->nextBlock(_PREHASH_InventoryBlock); msg->addU32Fast(_PREHASH_CallbackID, gInventoryCallbacks.registerCB(cb)); - msg->addUUIDFast(_PREHASH_FolderID, parent); + msg->addUUIDFast(_PREHASH_FolderID, parent_id); msg->addUUIDFast(_PREHASH_TransactionID, transaction_id); msg->addU32Fast(_PREHASH_NextOwnerMask, next_owner_perm); msg->addS8Fast(_PREHASH_Type, (S8)asset_type); -- cgit v1.3 From b68a67491026a055f0de9df349508b9e60a200ed Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Mon, 20 Mar 2023 22:06:20 +0200 Subject: SL-18629 Load cof only once links are ready --- indra/newview/llaisapi.cpp | 68 ++++++++++++++++++---------------- indra/newview/llappearancemgr.cpp | 46 +++++++++++++++++++++++ indra/newview/llappearancemgr.h | 1 + indra/newview/llinventoryfunctions.cpp | 13 +++++++ indra/newview/llinventoryfunctions.h | 14 +++++++ indra/newview/llinventorymodel.cpp | 16 ++++---- indra/newview/llinventorymodel.h | 3 +- 7 files changed, 121 insertions(+), 40 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index ece03d6988..d2bf7a0e9a 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -637,15 +637,17 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht bool needs_callback = true; LLUUID id(LLUUID::null); - if ( ( (type == COPYLIBRARYCATEGORY) - || (type == FETCHCATEGORYCATEGORIES) - || (type == FETCHCATEGORYCHILDREN)) - && result.has("category_id")) - { - id = result["category_id"]; - } - if (type == FETCHITEM) + switch (type) { + case COPYLIBRARYCATEGORY: + case FETCHCATEGORYCATEGORIES: + case FETCHCATEGORYCHILDREN: + if (result.has("category_id")) + { + id = result["category_id"]; + } + break; + case FETCHITEM: if (result.has("item_id")) { id = result["item_id"]; @@ -654,33 +656,35 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht { id = result["linked_id"]; } - } - if (type == CREATEINVENTORY) - { + break; + case CREATEINVENTORY: // CREATEINVENTORY can have multiple callbacks - if (result.has("_created_categories")) - { - LLSD& cats = result["_created_categories"]; - LLSD::array_const_iterator cat_iter; - for (cat_iter = cats.beginArray(); cat_iter != cats.endArray(); ++cat_iter) - { - LLUUID cat_id = *cat_iter; - callback(cat_id); + if (result.has("_created_categories")) + { + LLSD& cats = result["_created_categories"]; + LLSD::array_const_iterator cat_iter; + for (cat_iter = cats.beginArray(); cat_iter != cats.endArray(); ++cat_iter) + { + LLUUID cat_id = *cat_iter; + callback(cat_id); needs_callback = false; - } - } - if (result.has("_created_items")) - { - LLSD& items = result["_created_items"]; - LLSD::array_const_iterator item_iter; - for (item_iter = items.beginArray(); item_iter != items.endArray(); ++item_iter) - { - LLUUID item_id = *item_iter; - callback(item_id); + } + } + if (result.has("_created_items")) + { + LLSD& items = result["_created_items"]; + LLSD::array_const_iterator item_iter; + for (item_iter = items.beginArray(); item_iter != items.endArray(); ++item_iter) + { + LLUUID item_id = *item_iter; + callback(item_id); needs_callback = false; - } - } - } + } + } + break; + default: + break; + } if (needs_callback) { diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4e36a4c351..1de3cef3ba 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -40,6 +40,7 @@ #include "llgesturemgr.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" +#include "llinventorymodelbackgroundfetch.h" #include "llinventoryobserver.h" #include "llnotificationsutil.h" #include "lloutfitobserver.h" @@ -2416,6 +2417,46 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, LL_DEBUGS("Avatar") << self_av_string() << "starting" << LL_ENDL; + if (gInventory.hasPosiblyBrockenLinks()) + { + // Inventory has either broken links or links that + // haven't loaded yet and fetch is still in progress. + // Check if LLAppearanceMgr needs to wait. + LLUUID current_outfit_id = getCOF(); + LLInventoryModel::item_array_t cof_items; + LLInventoryModel::cat_array_t cof_cats; + LLFindBrokenLinks is_brocken_link; + gInventory.collectDescendentsIf(current_outfit_id, + cof_cats, + cof_items, + LLInventoryModel::EXCLUDE_TRASH, + is_brocken_link); + + if (cof_items.size() > 0) + { + // Some links haven't loaded yet, but fetch isn't complete so + // links are likely fine and we will have to wait for them to + // load (if inventory takes too long to load, might be a good + // idea to make this check periodical) + if (!mBulkFecthCallbackSlot.connected()) + { + nullary_func_t cb = post_update_func; + mBulkFecthCallbackSlot = + LLInventoryModelBackgroundFetch::getInstance()->setAllFoldersFetchedCallback( + [this, enforce_ordering, post_update_func, cb]() + { + // inventory model should be already tracking this + // callback, but make sure rebuildBrockenLinks gets + // called before a cof update + gInventory.rebuildBrockenLinks(); + updateAppearanceFromCOF(enforce_ordering, post_update_func, post_update_func); + mBulkFecthCallbackSlot.disconnect(); + }); + } + return; + } + } + if (enforce_item_restrictions) { // The point here is just to call @@ -4213,6 +4254,11 @@ LLAppearanceMgr::LLAppearanceMgr(): LLAppearanceMgr::~LLAppearanceMgr() { mActive = false; + + if (!mBulkFecthCallbackSlot.connected()) + { + mBulkFecthCallbackSlot.disconnect(); + } } void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val) diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 8a55a848db..53b8098a44 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -263,6 +263,7 @@ private: bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls. bool mOutstandingAppearanceBakeRequest; // A bake request is outstanding. Do not overlap. bool mRerequestAppearanceBake; + boost::signals2::connection mBulkFecthCallbackSlot; /** * Lock for blocking operations on outfit until server reply or timeout exceed diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index c2e9137910..dd116ce2d2 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2274,6 +2274,19 @@ bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat, } } +bool LLFindBrokenLinks::operator()(LLInventoryCategory* cat, + LLInventoryItem* item) +{ + // only for broken links getType will be a link + // otherwise it's supposed to have the type of an item + // it is linked too + if (item && LLAssetType::lookupIsLinkType(item->getType())) + { + return TRUE; + } + return FALSE; +} + bool LLFindWearables::operator()(LLInventoryCategory* cat, LLInventoryItem* item) { diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index ec5e53f9a6..1cc778f8a5 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -360,6 +360,20 @@ public: }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLFindBrokenLinks +// +// Collects broken links +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLFindBrokenLinks : public LLInventoryCollectFunctor +{ +public: + LLFindBrokenLinks() {} + virtual ~LLFindBrokenLinks() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item); +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLFindByMask //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index b82f0c3ede..b833571ee9 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -440,7 +440,7 @@ LLInventoryModel::LLInventoryModel() mIsNotifyObservers(FALSE), mModifyMask(LLInventoryObserver::ALL), mChangedItemIDs(), - mBulckFecthCallbackSlot(), + mBulkFecthCallbackSlot(), mObservers(), mHttpRequestFG(NULL), mHttpRequestBG(NULL), @@ -473,9 +473,9 @@ void LLInventoryModel::cleanupInventory() delete observer; } - if (mBulckFecthCallbackSlot.connected()) + if (mBulkFecthCallbackSlot.connected()) { - mBulckFecthCallbackSlot.disconnect(); + mBulkFecthCallbackSlot.disconnect(); } mObservers.clear(); @@ -1764,6 +1764,7 @@ void LLInventoryModel::rebuildBrockenLinks() addChangedMask(LLInventoryObserver::REBUILD, link_id); } mPossiblyBrockenLinks.clear(); + notifyObservers(); } // Does not appear to be used currently. @@ -2389,16 +2390,17 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) // isEverythingFetched is actually 'initial' fetch only. // Schedule this link for a recheck once inventory gets loaded mPossiblyBrockenLinks.insert(item->getUUID()); - if (!mBulckFecthCallbackSlot.connected()) + if (!mBulkFecthCallbackSlot.connected()) { // Links might take a while to update this way, and there // might be a lot of them. A better option might be to check // links periodically with final check on fetch completion. - mBulckFecthCallbackSlot = + mBulkFecthCallbackSlot = LLInventoryModelBackgroundFetch::getInstance()->setAllFoldersFetchedCallback( - []() + [this]() { - gInventory.rebuildBrockenLinks(); + rebuildBrockenLinks(); + mBulkFecthCallbackSlot.disconnect(); }); } LL_DEBUGS(LOG_INV) << "Scheduling a link to be rebuilt later [ name: " << item->getName() diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 02278ed957..ac6eda02d8 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -410,6 +410,7 @@ public: // Marks links from a "possibly" broken list for a rebuild // clears the list void rebuildBrockenLinks(); + bool hasPosiblyBrockenLinks() const { return mPossiblyBrockenLinks.size() > 0; } //-------------------------------------------------------------------- // Delete @@ -579,7 +580,7 @@ private: changed_items_t mChangedItemIDsBacklog; changed_items_t mAddedItemIDsBacklog; changed_items_t mPossiblyBrockenLinks; - boost::signals2::connection mBulckFecthCallbackSlot; + boost::signals2::connection mBulkFecthCallbackSlot; //-------------------------------------------------------------------- -- cgit v1.3 From 6fd7427c576ec922b6c670b4ff9381c7cb738b5b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sun, 26 Mar 2023 13:44:50 +0300 Subject: SL-18003 Bulk fetch some items by fetching whole folder --- indra/newview/llaisapi.cpp | 4 +- indra/newview/llappearancemgr.cpp | 64 +++++++++++++++++++++++ indra/newview/llinventorymodelbackgroundfetch.cpp | 6 ++- indra/newview/llinventoryobserver.cpp | 1 + indra/newview/llinventoryobserver.h | 2 +- indra/newview/llviewerinventory.cpp | 2 +- 6 files changed, 75 insertions(+), 4 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index d204a752ec..6a43c901e7 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -373,7 +373,6 @@ void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t /*static*/ void AISAPI::FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callback) { - std::string cap; cap = (type == INVENTORY) ? getInvCap() : getLibCap(); @@ -859,6 +858,7 @@ void AISUpdate::parseItem(const LLSD& item_map) { mItemsCreated[item_id] = new_item; mCatDescendentDeltas[new_item->getParentUUID()]++; + new_item->setComplete(true); } } else @@ -893,6 +893,7 @@ void AISUpdate::parseLink(const LLSD& link_map) //LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << LL_ENDL; mItemsCreated[item_id] = new_link; mCatDescendentDeltas[parent_id]; + new_link->setComplete(true); } else if (curr_link) { @@ -913,6 +914,7 @@ void AISUpdate::parseLink(const LLSD& link_map) //LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << LL_ENDL; mItemsCreated[item_id] = new_link; mCatDescendentDeltas[parent_id]++; + new_link->setComplete(true); } } else diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 1de3cef3ba..b36ea1c457 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4385,6 +4385,70 @@ public: ~CallAfterCategoryFetchStage1() { } + /*virtual*/ void startFetch() + { + bool ais3 = AISAPI::isAvailable(); + for (uuid_vec_t::const_iterator it = mIDs.begin(); it != mIDs.end(); ++it) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(*it); + if (!cat) continue; + if (!isCategoryComplete(cat)) + { + // CHECK IT: isCategoryComplete() checks both version and descendant count but + // fetch() only works for Unknown version and doesn't care about descentants, + // as result fetch won't start and folder will potentially get stuck as + // incomplete in observer. + // Likely either both should use only version or both should check descendants. + cat->fetch(); //blindly fetch it without seeing if anything else is fetching it. + mIncomplete.push_back(*it); //Add to list of things being downloaded for this observer. + } + else if (ais3) + { + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items); + + if (items) + { + S32 complete_count = 0; + S32 incomplete_count = 0; + for (LLInventoryModel::item_array_t::const_iterator it = items->begin(); it < items->end(); ++it) + { + if (!(*it)->isFinished()) + { + incomplete_count++; + } + else + { + complete_count++; + } + } + // AIS can fetch couple items, but if there + // is more than a dozen it will be very slow + // it's faster to get whole folder in such case + const S32 MAX_INDIVIDUAL_FETCH = 10; + if (incomplete_count > MAX_INDIVIDUAL_FETCH + || (incomplete_count > 1 && complete_count == 0)) + { + // To prevent premature removal from mIncomplete and + // since we are doing a full refetch anyway, mark unknown + cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN); + LLInventoryModelBackgroundFetch::instance().start(*it, false); + mIncomplete.push_back(*it); + } + else + { + // let stage2 handle incomplete ones + mComplete.push_back(*it); + } + } + } + else + { + mComplete.push_back(*it); + } + } + } virtual void done() { if (mComplete.size() <= 0) diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 023cc05ee7..0d366e43f4 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -31,8 +31,9 @@ #include "llagent.h" #include "llappviewer.h" #include "llcallbacklist.h" -#include "llinventorypanel.h" #include "llinventorymodel.h" +#include "llinventoryobserver.h" +#include "llinventorypanel.h" #include "llstartup.h" #include "llviewercontrol.h" #include "llviewerinventory.h" @@ -349,6 +350,9 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched() //LL_INFOS(LOG_INV) << "All folders fetched, validating" << LL_ENDL; //gInventory.validate(); + gInventory.addChangedMask(LLInventoryObserver::INTERNAL, gInventory.getRootFolderID()); + gInventory.addChangedMask(LLInventoryObserver::INTERNAL, gInventory.getLibraryRootFolderID()); + // For now only informs about initial fetch being done mAllFoldersFetchedSignal(); } diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 25f1854765..79917fb11b 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -40,6 +40,7 @@ #include "llaisapi.h" #include "llfloater.h" #include "llfocusmgr.h" +#include "llinventorymodelbackgroundfetch.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 02f73a5892..f0ed2f7003 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -126,7 +126,7 @@ public: LLInventoryFetchDescendentsObserver(const LLUUID& cat_id = LLUUID::null); LLInventoryFetchDescendentsObserver(const uuid_vec_t& cat_ids); - /*virtual*/ void startFetch(); + virtual void startFetch(); /*virtual*/ void changed(U32 mask); protected: BOOL isCategoryComplete(const LLViewerInventoryCategory* cat) const; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index d8de269c3c..6c7e815b04 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -671,7 +671,7 @@ bool LLViewerInventoryCategory::fetch() } if (!url.empty() || AISAPI::isAvailable()) { - LLInventoryModelBackgroundFetch::instance().start(mUUID, false); + LLInventoryModelBackgroundFetch::instance().start(mUUID, false); } return true; } -- cgit v1.3 From 89a8c96f36983738645a2116d9d432e3bd88f1df Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 28 Mar 2023 02:27:34 +0300 Subject: SL-18003 Bulk download items when possible And signal fodler fetch completion when folder of recursive fetch is done, do not hold it for individual items --- indra/newview/llappearancemgr.cpp | 42 ++++++--- indra/newview/llinventorymodel.cpp | 13 ++- indra/newview/llinventorymodelbackgroundfetch.cpp | 89 +++++++++++++----- indra/newview/llinventorymodelbackgroundfetch.h | 10 +- indra/newview/llinventoryobserver.cpp | 106 +++++++++++++++++----- indra/newview/llsidepanelinventory.cpp | 2 +- indra/newview/llviewerinventory.cpp | 9 +- 7 files changed, 191 insertions(+), 80 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index b36ea1c457..8e44411d52 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2420,7 +2420,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, if (gInventory.hasPosiblyBrockenLinks()) { // Inventory has either broken links or links that - // haven't loaded yet and fetch is still in progress. + // haven't loaded yet. // Check if LLAppearanceMgr needs to wait. LLUUID current_outfit_id = getCOF(); LLInventoryModel::item_array_t cof_items; @@ -2438,22 +2438,34 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, // links are likely fine and we will have to wait for them to // load (if inventory takes too long to load, might be a good // idea to make this check periodical) - if (!mBulkFecthCallbackSlot.connected()) + if (LLInventoryModelBackgroundFetch::getInstance()->folderFetchActive()) { - nullary_func_t cb = post_update_func; - mBulkFecthCallbackSlot = - LLInventoryModelBackgroundFetch::getInstance()->setAllFoldersFetchedCallback( - [this, enforce_ordering, post_update_func, cb]() + if (!mBulkFecthCallbackSlot.connected()) { - // inventory model should be already tracking this - // callback, but make sure rebuildBrockenLinks gets - // called before a cof update - gInventory.rebuildBrockenLinks(); - updateAppearanceFromCOF(enforce_ordering, post_update_func, post_update_func); - mBulkFecthCallbackSlot.disconnect(); - }); + nullary_func_t cb = post_update_func; + mBulkFecthCallbackSlot = + LLInventoryModelBackgroundFetch::getInstance()->setFetchCompletionCallback( + [this, enforce_ordering, post_update_func, cb]() + { + // inventory model should be already tracking this + // callback, but make sure rebuildBrockenLinks gets + // called before a cof update + gInventory.rebuildBrockenLinks(); + updateAppearanceFromCOF(enforce_ordering, post_update_func, post_update_func); + mBulkFecthCallbackSlot.disconnect(); + }); + } + return; + } + else + { + // this should have happened on completion callback, + // check why it didn't then fix it + llassert(false); + + // try to recover now + gInventory.rebuildBrockenLinks(); } - return; } } @@ -4433,7 +4445,7 @@ public: // To prevent premature removal from mIncomplete and // since we are doing a full refetch anyway, mark unknown cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN); - LLInventoryModelBackgroundFetch::instance().start(*it, false); + cat->fetch(); mIncomplete.push_back(*it); } else diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 47fd17ef86..bfc7840708 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1762,7 +1762,7 @@ void LLInventoryModel::rebuildBrockenLinks() // make sure we aren't adding expensive Rebuild to anything else. notifyObservers(); - for (LLUUID link_id : mPossiblyBrockenLinks) + for (const LLUUID &link_id : mPossiblyBrockenLinks) { addChangedMask(LLInventoryObserver::REBUILD, link_id); } @@ -2388,7 +2388,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) // The item will show up as a broken link. if (item->getIsBrokenLink()) { - if (!LLInventoryModelBackgroundFetch::getInstance()->isEverythingFetched()) + if (LLInventoryModelBackgroundFetch::getInstance()->folderFetchActive()) { // isEverythingFetched is actually 'initial' fetch only. // Schedule this link for a recheck once inventory gets loaded @@ -2399,7 +2399,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) // might be a lot of them. A better option might be to check // links periodically with final check on fetch completion. mBulkFecthCallbackSlot = - LLInventoryModelBackgroundFetch::getInstance()->setAllFoldersFetchedCallback( + LLInventoryModelBackgroundFetch::getInstance()->setFetchCompletionCallback( [this]() { rebuildBrockenLinks(); @@ -3798,7 +3798,10 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) // Temporary workaround: just fetch the item using AIS to get missing fields. // If this works fine we might want to extract ids only from the message // then use AIS as a primary fetcher - LLInventoryModelBackgroundFetch::instance().start((*cit)->getUUID(), false); + + // Use AIS derectly to not reset folder's version + // Todo: May be LLInventoryModelBackgroundFetch needs a 'forced' option + AISAPI::FetchCategoryChildren((*cit)->getUUID(), AISAPI::INVENTORY); } for (item_array_t::iterator iit = items.begin(); iit != items.end(); ++iit) { @@ -3807,7 +3810,7 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) // Temporary workaround: just fetch the item using AIS to get missing fields. // If this works fine we might want to extract ids only from the message // then use AIS as a primary fetcher - LLInventoryModelBackgroundFetch::instance().start((*iit)->getUUID(), false); + LLInventoryModelBackgroundFetch::instance().scheduleItemFetch((*iit)->getUUID()); } gInventory.notifyObservers(); diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 25e35915c3..d58dd22ca1 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -190,6 +190,7 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch(): mBackgroundFetchActive(false), mFolderFetchActive(false), mFetchCount(0), + mFetchFolderCount(0), mAllFoldersFetched(false), mRecursiveInventoryFetchStarted(false), mRecursiveLibraryFetchStarted(false), @@ -204,6 +205,11 @@ bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const return mFetchFolderQueue.empty() && mFetchItemQueue.empty() && mFetchCount <= 0; } +bool LLInventoryModelBackgroundFetch::isFolderFetchProcessingComplete() const +{ + return mFetchFolderQueue.empty() && mFetchFolderCount <= 0; +} + bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const { return mRecursiveLibraryFetchStarted; @@ -338,16 +344,24 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) } else if (LLViewerInventoryItem * itemp = gInventory.getItem(id)) { - if (! itemp->mIsComplete && (mFetchItemQueue.empty() || mFetchItemQueue.front().mUUID != id)) + if (! itemp->mIsComplete) { - mBackgroundFetchActive = true; - - mFetchItemQueue.push_front(FetchQueueInfo(id, RT_NONE, false)); - gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + scheduleItemFetch(id); } } } +void LLInventoryModelBackgroundFetch::scheduleItemFetch(const LLUUID& item_id) +{ + if (mFetchItemQueue.empty() || mFetchItemQueue.front().mUUID != item_id) + { + mBackgroundFetchActive = true; + + mFetchItemQueue.push_front(FetchQueueInfo(item_id, RT_NONE, false)); + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + } +} + void LLInventoryModelBackgroundFetch::findLostItems() { if (AISAPI::isAvailable()) @@ -371,18 +385,23 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched() mAllFoldersFetched = true; //LL_INFOS(LOG_INV) << "All folders fetched, validating" << LL_ENDL; //gInventory.validate(); - - // For now only informs about initial fetch being done - mAllFoldersFetchedSignal(); } + mFolderFetchActive = false; - mBackgroundFetchActive = false; + if (isBulkFetchProcessingComplete()) + { + mBackgroundFetchActive = false; + } + + // For now only informs about initial fetch being done + mFoldersFetchedSignal(); + LL_INFOS(LOG_INV) << "Inventory background fetch completed" << LL_ENDL; } -boost::signals2::connection LLInventoryModelBackgroundFetch::setAllFoldersFetchedCallback(folders_fetched_callback_t cb) +boost::signals2::connection LLInventoryModelBackgroundFetch::setFetchCompletionCallback(folders_fetched_callback_t cb) { - return mAllFoldersFetchedSignal.connect(cb); + return mFoldersFetchedSignal.connect(cb); } void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *) @@ -415,10 +434,20 @@ void LLInventoryModelBackgroundFetch::incrFetchCount(S32 fetching) mFetchCount = 0; } } +void LLInventoryModelBackgroundFetch::incrFetchFolderCount(S32 fetching) +{ + incrFetchCount(fetching); + mFetchFolderCount += fetching; + if (mFetchCount < 0) + { + LL_WARNS_ONCE(LOG_INV) << "Inventory fetch count fell below zero (0)." << LL_ENDL; + mFetchFolderCount = 0; + } +} void ais_simple_folder_callback(const LLUUID& inv_id) { - LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); + LLInventoryModelBackgroundFetch::instance().incrFetchFolderCount(-1); LLViewerInventoryCategory * cat(gInventory.getCategory(inv_id)); if (cat) cat->setFetching(false); } @@ -430,7 +459,7 @@ void ais_simple_item_callback(const LLUUID& inv_id) void LLInventoryModelBackgroundFetch::onAISFodlerCalback(const LLUUID &request_id, const LLUUID &response_id, ERecursionType recursion) { - incrFetchCount(-1); + incrFetchFolderCount(-1); if (response_id.isNull()) // Failure { if (recursion == RT_RECURSIVE) @@ -464,13 +493,13 @@ void LLInventoryModelBackgroundFetch::onAISFodlerCalback(const LLUUID &request_i gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } + } - // done - LLViewerInventoryCategory * cat(gInventory.getCategory(request_id)); - if (cat) - { - cat->setFetching(false); - } + // done + LLViewerInventoryCategory * cat(gInventory.getCategory(request_id)); + if (cat) + { + cat->setFetching(false); } } @@ -516,10 +545,15 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() curent_time = LLTimer::getTotalSeconds(); } - if (isBulkFetchProcessingComplete()) + if (isFolderFetchProcessingComplete() && mFolderFetchActive) { setAllFoldersFetched(); } + + if (isBulkFetchProcessingComplete()) + { + mBackgroundFetchActive = false; + } } void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetch_info) @@ -532,7 +566,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc LL_WARNS() << "Lost and found not implemented yet" << LL_ENDL; // todo: needs to be requested from ais in special manner? /*AISAPI::FetchCategoryChildren(LLUUID::null, AISAPI::INVENTORY, false, ais_simple_callback); - mFetchCount++;*/ + incrFetchFolderCount(1);*/ } else { @@ -559,7 +593,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc LLInventoryModelBackgroundFetch::instance().onAISFodlerCalback(cat_id, response_id, type); }); } - mFetchCount++; + incrFetchFolderCount(1); cat->setFetching(true); } else @@ -590,14 +624,19 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc { if (itemp->getPermissions().getOwner() == gAgent.getID()) { - AISAPI::FetchItem(itemp->getUUID(), AISAPI::INVENTORY, ais_simple_item_callback); + AISAPI::FetchItem(fetch_info.mUUID, AISAPI::INVENTORY, ais_simple_item_callback); } else { - AISAPI::FetchItem(itemp->getUUID(), AISAPI::LIBRARY, ais_simple_item_callback); + AISAPI::FetchItem(fetch_info.mUUID, AISAPI::LIBRARY, ais_simple_item_callback); } - mFetchCount++; } + else + { + // Assume agent's inventory, library wouldn't have gotten here + AISAPI::FetchItem(fetch_info.mUUID, AISAPI::INVENTORY, ais_simple_item_callback); + } + mFetchCount++; } } diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 0a5608c0c6..6a8b616a82 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -47,9 +47,10 @@ class LLInventoryModelBackgroundFetch : public LLSingleton folders_fetched_callback_t; - boost::signals2::connection setAllFoldersFetchedCallback(folders_fetched_callback_t cb); + boost::signals2::connection setFetchCompletionCallback(folders_fetched_callback_t cb); void addRequestAtFront(const LLUUID & id, bool recursive, bool is_category); void addRequestAtBack(const LLUUID & id, bool recursive, bool is_category); @@ -110,11 +113,12 @@ private: bool mRecursiveLibraryFetchStarted; bool mAllFoldersFetched; typedef boost::signals2::signal folders_fetched_signal_t; - folders_fetched_signal_t mAllFoldersFetchedSignal; + folders_fetched_signal_t mFoldersFetchedSignal; bool mBackgroundFetchActive; bool mFolderFetchActive; S32 mFetchCount; + S32 mFetchFolderCount; LLFrameTimer mFetchTimer; F32 mMinTimeBetweenFetches; diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index fe33be4abe..4db913ed0d 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -255,29 +255,19 @@ void LLInventoryFetchItemsObserver::startFetch() { bool aisv3 = AISAPI::isAvailable(); - LLUUID owner_id; LLSD items_llsd; + + typedef std::map requests_by_fodlers_t; + requests_by_fodlers_t requests; for (uuid_vec_t::const_iterator it = mIDs.begin(); it < mIDs.end(); ++it) { - LLViewerInventoryItem* item = gInventory.getItem(*it); - if (item) - { - if (item->isFinished()) - { - // It's complete, so put it on the complete container. - mComplete.push_back(*it); - continue; - } - else - { - owner_id = item->getPermissions().getOwner(); - } - } - else - { - // assume it's agent inventory. - owner_id = gAgent.getID(); - } + LLViewerInventoryItem* item = gInventory.getItem(*it); + if (item && item->isFinished()) + { + // It's complete, so put it on the complete container. + mComplete.push_back(*it); + continue; + } // Ignore categories since they're not items. We // could also just add this to mComplete but not sure what the @@ -300,13 +290,31 @@ void LLInventoryFetchItemsObserver::startFetch() if (aisv3) { - LLInventoryModelBackgroundFetch::getInstance()->start(*it); + if (item) + { + LLUUID parent_id = item->getParentUUID(); + requests[parent_id].push_back(*it); + } + else + { + // Can happen for gestures and calling cards if server notified us before they fetched + // Request by id without checking for an item. + LLInventoryModelBackgroundFetch::getInstance()->scheduleItemFetch(*it); + } } else { // Prepare the data to fetch LLSD item_entry; - item_entry["owner_id"] = owner_id; + if (item) + { + item_entry["owner_id"] = item->getPermissions().getOwner(); + } + else + { + // assume it's agent inventory. + item_entry["owner_id"] = gAgent.getID(); + } item_entry["item_id"] = (*it); items_llsd.append(item_entry); } @@ -315,7 +323,59 @@ void LLInventoryFetchItemsObserver::startFetch() mFetchingPeriod.reset(); mFetchingPeriod.setTimerExpirySec(FETCH_TIMER_EXPIRY); - if (!aisv3) + if (aisv3) + { + const S32 MAX_INDIVIDUAL_REQUESTS = 10; + for (requests_by_fodlers_t::value_type &folder : requests) + { + if (folder.second.size() > MAX_INDIVIDUAL_REQUESTS) + { + // requesting one by one will take a while + // do whole folder + LLInventoryModelBackgroundFetch::getInstance()->start(folder.first); + } + else + { + LLViewerInventoryCategory* cat = gInventory.getCategory(folder.first); + if (cat) + { + if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + // start fetching whole folder since it's not ready either way + cat->fetch(); + } + else if (cat->getViewerDescendentCount() <= folder.second.size()) + { + // start fetching whole folder since we need all items + cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN); + cat->fetch(); + + } + else + { + // get items one by one + for (LLUUID &item_id : folder.second) + { + LLInventoryModelBackgroundFetch::getInstance()->scheduleItemFetch(item_id); + } + } + } + else + { + // Isn't supposed to happen? We should have all folders + // and if item exists, folder is supposed to exist as well. + llassert(false); + + // get items one by one + for (LLUUID &item_id : folder.second) + { + LLInventoryModelBackgroundFetch::getInstance()->scheduleItemFetch(item_id); + } + } + } + } + } + else { fetch_items_from_llsd(items_llsd); } diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index de0330588b..bd6f846268 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -545,7 +545,7 @@ void LLSidepanelInventory::clearSelections(bool clearMain, bool clearInbox) } } - if (clearInbox && mInboxEnabled && mInventoryPanelInbox.get()) + if (clearInbox && mInboxEnabled && !mInventoryPanelInbox.isDead()) { mInventoryPanelInbox.get()->getRootFolder()->clearSelection(); } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 6bd86f7902..6f62ba5409 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -432,14 +432,7 @@ void LLViewerInventoryItem::fetchFromServer(void) const { if (AISAPI::isAvailable()) // AIS v 3 { - if (gAgent.getID() != mPermissions.getOwner()) - { - AISAPI::FetchItem(mUUID, AISAPI::LIBRARY); - } - else - { - AISAPI::FetchItem(mUUID, AISAPI::INVENTORY); - } + LLInventoryModelBackgroundFetch::getInstance()->scheduleItemFetch(mUUID); } else { -- cgit v1.3 From 11b2f138cecc123c3e6876b56ea63c5fbd734d56 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 29 Mar 2023 04:28:07 +0300 Subject: SL-19502 Copying folders should copy thumbnails --- indra/newview/llappearancemgr.cpp | 7 ++----- indra/newview/llinventorybridge.cpp | 3 ++- indra/newview/llinventoryfunctions.cpp | 2 +- indra/newview/llinventorygallery.cpp | 2 +- indra/newview/llinventorymodel.cpp | 4 +++- indra/newview/llinventorymodel.h | 3 ++- 6 files changed, 11 insertions(+), 10 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 8e44411d52..a4dc0c341e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2786,8 +2786,6 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap pid = gInventory.getRootFolderID(); } - // UDP PATH - // D567 needs to carry over thumbnail info if present gInventory.createNewCategory( pid, LLFolderType::FT_NONE, @@ -2807,7 +2805,8 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap // BAP fixes a lag in display of created dir. gInventory.notifyObservers(); - } + }, + cat->getThumbnailUUID() ); } else @@ -4050,8 +4049,6 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo // First, make a folder in the My Outfits directory. const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); - // UDP PATH, should remove - // D567 copy thumbnail info from source folder gInventory.createNewCategory( parent_id, LLFolderType::FT_OUTFIT, diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 1fac4dd1ad..86a3fb8ec0 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4965,7 +4965,8 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat) gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), - func); + func, + inv_cat->getThumbnailUUID()); } void LLFolderBridge::outfitFolderCreatedCallback(LLUUID cat_source_id, LLUUID cat_dest_id) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 5b46dc4753..fbcce5f078 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -406,7 +406,7 @@ void copy_inventory_category(LLInventoryModel* model, // Create the initial folder // D567 needs to handle new fields inventory_func_type func = boost::bind(©_inventory_category_content, _1, model, cat, root_copy_id, move_no_copy_items); - gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func); + gInventory.createNewCategory(parent_id, LLFolderType::FT_NONE, cat->getName(), func, cat->getThumbnailUUID()); } void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryModel* model, LLViewerInventoryCategory* cat, const LLUUID& root_copy_id, bool move_no_copy_items) diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 2624640bb4..08836555d4 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -1900,6 +1900,6 @@ void dropToMyOutfits(LLInventoryCategory* inv_cat) // Note: creation will take time, so passing folder id to callback is slightly unreliable, // but so is collecting and passing descendants' ids inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1); - gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func); + gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 9a874350bf..70ff07c0c2 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -966,7 +966,8 @@ const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::ETyp void LLInventoryModel::createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, const std::string& pname, - inventory_func_type callback) + inventory_func_type callback, + const LLUUID& thumbnail_id) { if (!isInventoryUsable()) { @@ -1008,6 +1009,7 @@ void LLInventoryModel::createNewCategory(const LLUUID& parent_id, LLSD new_inventory = LLSD::emptyMap(); new_inventory["categories"] = LLSD::emptyArray(); LLViewerInventoryCategory cat(LLUUID::null, parent_id, preferred_type, name, gAgent.getID()); + cat.setThumbnailUUID(thumbnail_id); LLSD cat_sd = cat.asLLSD(); new_inventory["categories"].append(cat_sd); AISAPI::CreateInventory( diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index ac6eda02d8..dcd1e87fa7 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -482,7 +482,8 @@ public: void createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, const std::string& name, - inventory_func_type callback = NULL); + inventory_func_type callback = NULL, + const LLUUID& thumbnail_id = LLUUID::null); protected: // Internal methods that add inventory and make sure that all of // the internal data structures are consistent. These methods -- cgit v1.3 From d33328584f331287cce626804e10c962e7c3ce48 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 8 Apr 2023 02:42:39 +0300 Subject: SL-19529 Fix uninitialized variable and calback counter --- indra/newview/llappearancemgr.cpp | 5 ++--- indra/newview/llinventoryfunctions.cpp | 20 ++++++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index a4dc0c341e..59bf418a00 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1702,8 +1702,6 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds { parent_id = gInventory.getRootFolderID(); } - // USES UDP PATH - // D567 needs to carry over thumbnail info gInventory.createNewCategory( parent_id, LLFolderType::FT_NONE, @@ -1713,7 +1711,8 @@ void LLAppearanceMgr::shallowCopyCategory(const LLUUID& src_id, const LLUUID& ds LLAppearanceMgr::getInstance()->shallowCopyCategoryContents(src_id, new_id, cb); gInventory.notifyObservers(); - } + }, + src_cat->getThumbnailUUID() ); } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 00ff0e83c0..dd3750c152 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1649,16 +1649,20 @@ void validate_marketplacelistings( gInventory.createNewCategory(parent_uuid, LLFolderType::FT_NONE, cat->getName(), - [cat_uuid, cb_result, cb_msg, fix_hierarchy, depth, notify_observers](const LLUUID &new_cat_id) + [cat_uuid, cb_result, cb_msg, fix_hierarchy, depth](const LLUUID &new_cat_id) { + if (new_cat_id.isNull()) + { + cb_result(0, false); + return; + } LLInventoryCategory * move_cat = gInventory.getCategory(cat_uuid); LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *)(move_cat); LLInventoryCategory * new_cat = gInventory.getCategory(new_cat_id); gInventory.changeCategoryParent(viewer_cat, new_cat_id, false); S32 pending = 0; bool result = true; - // notify_observers probably should be true in such case? - validate_marketplacelistings(new_cat, cb_result, cb_msg, fix_hierarchy, depth + 1, notify_observers, pending, result); + validate_marketplacelistings(new_cat, cb_result, cb_msg, fix_hierarchy, depth + 1, true, pending, result); cb_result(pending, result); } ); @@ -2306,8 +2310,11 @@ bool can_share_item(const LLUUID& item_id) LLMarketplaceValidator::LLMarketplaceValidator() + : mPendingCallbacks(0) + , mValidationInProgress(false) { } + LLMarketplaceValidator::~LLMarketplaceValidator() { } @@ -2335,7 +2342,7 @@ void LLMarketplaceValidator::start() return; } mValidationInProgress = true; - mPendingCallbacks = 1; // do '1' in case something decides ro callback immediately + mPendingCallbacks = 1; // do '1' in case something decides to callback immediately const ValidationRequest &first = mValidationQueue.front(); LLViewerInventoryCategory* cat = gInventory.getCategory(first.mCategoryId); @@ -2358,6 +2365,7 @@ void LLMarketplaceValidator::start() } }; + S32 pending_calbacks = 0; validate_marketplacelistings( cat, result_callback, @@ -2365,10 +2373,10 @@ void LLMarketplaceValidator::start() first.mFixHierarchy, first.mDepth, true, - mPendingCallbacks, + pending_calbacks, mPendingResult); - result_callback(mPendingCallbacks, mPendingResult); + result_callback(pending_calbacks, mPendingResult); } LLMarketplaceValidator::ValidationRequest::ValidationRequest( -- cgit v1.3 From 53f2e1710aab77361085fe2c2a41fea87ede0fb8 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 13 Apr 2023 02:20:33 +0300 Subject: SL-19533 Faster declouding --- indra/newview/llaisapi.cpp | 3 +- indra/newview/llappearancemgr.cpp | 98 ++++++++++++++++------- indra/newview/llappearancemgr.h | 1 - indra/newview/llinventorymodel.cpp | 50 ++++++++++-- indra/newview/llinventorymodel.h | 4 +- indra/newview/llinventorymodelbackgroundfetch.cpp | 20 +++-- indra/newview/llviewerinventory.cpp | 1 + 7 files changed, 126 insertions(+), 51 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index ef3305a69d..7a87fc6c3d 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -707,6 +707,8 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht httpOptions->setTimeout(180); + LL_DEBUGS("Inventory") << "Request url: " << url << LL_ENDL; + LLSD result; LLSD httpResults; LLCore::HttpStatus status; @@ -721,7 +723,6 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht F32MillisecondsImplicit elapsed_time = ais_timer.getElapsedTimeF32(); LL_DEBUGS("Inventory") << "Request type: " << (S32)type - << " \nRequest url: " << url << " \nRequest target: " << targetId << " \nElapsed time ince request: " << elapsed_time << " \nstatus: " << status.toULong() << LL_ENDL; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 59bf418a00..e160b5813f 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -586,6 +586,66 @@ LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOn } } +class LLBrokenLinkObserver : public LLInventoryObserver +{ +public: + LLUUID mUUID; + bool mEnforceItemRestrictions; + bool mEnforceOrdering; + nullary_func_t mPostUpdateFunc; + + LLBrokenLinkObserver(const LLUUID& uuid, + bool enforce_item_restrictions , + bool enforce_ordering , + nullary_func_t post_update_func) : + mUUID(uuid), + mEnforceItemRestrictions(enforce_item_restrictions), + mEnforceOrdering(enforce_ordering), + mPostUpdateFunc(post_update_func) + { + } + /* virtual */ void changed(U32 mask); + void postProcess(); +}; + +void LLBrokenLinkObserver::changed(U32 mask) +{ + if (mask & LLInventoryObserver::REBUILD) + { + // This observer should be executed after LLInventoryPanel::itemChanged(), + // but if it isn't, consider calling updateAppearanceFromCOF with a delay + const uuid_set_t& changed_item_ids = gInventory.getChangedIDs(); + for (uuid_set_t::const_iterator it = changed_item_ids.begin(); it != changed_item_ids.end(); ++it) + { + const LLUUID& id = *it; + if (id == mUUID) + { + // Might not be processed yet and it is not a + // good idea to update appearane here, postpone. + doOnIdleOneTime([this]() + { + postProcess(); + }); + + gInventory.removeObserver(this); + return; + } + } + } +} + +void LLBrokenLinkObserver::postProcess() +{ + LLViewerInventoryItem* item = gInventory.getItem(mUUID); + llassert(item && !item->getIsBrokenLink()); // the whole point was to get a correct link + + LLAppearanceMgr::instance().updateAppearanceFromCOF( + mEnforceItemRestrictions , + mEnforceOrdering , + mPostUpdateFunc); + delete this; +} + struct LLFoundData { @@ -2435,35 +2495,16 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions, { // Some links haven't loaded yet, but fetch isn't complete so // links are likely fine and we will have to wait for them to - // load (if inventory takes too long to load, might be a good - // idea to make this check periodical) + // load if (LLInventoryModelBackgroundFetch::getInstance()->folderFetchActive()) { - if (!mBulkFecthCallbackSlot.connected()) - { - nullary_func_t cb = post_update_func; - mBulkFecthCallbackSlot = - LLInventoryModelBackgroundFetch::getInstance()->setFetchCompletionCallback( - [this, enforce_ordering, post_update_func, cb]() - { - // inventory model should be already tracking this - // callback, but make sure rebuildBrockenLinks gets - // called before a cof update - gInventory.rebuildBrockenLinks(); - updateAppearanceFromCOF(enforce_ordering, post_update_func, post_update_func); - mBulkFecthCallbackSlot.disconnect(); - }); - } - return; - } - else - { - // this should have happened on completion callback, - // check why it didn't then fix it - llassert(false); - // try to recover now - gInventory.rebuildBrockenLinks(); + LLBrokenLinkObserver* observer = new LLBrokenLinkObserver(cof_items.front()->getUUID(), + enforce_item_restrictions, + enforce_ordering, + post_update_func); + gInventory.addObserver(observer); + return; } } } @@ -4262,11 +4303,6 @@ LLAppearanceMgr::LLAppearanceMgr(): LLAppearanceMgr::~LLAppearanceMgr() { mActive = false; - - if (!mBulkFecthCallbackSlot.connected()) - { - mBulkFecthCallbackSlot.disconnect(); - } } void LLAppearanceMgr::setAttachmentInvLinkEnable(bool val) diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index edb4be83bb..cf953d21ac 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -264,7 +264,6 @@ private: bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls. bool mOutstandingAppearanceBakeRequest; // A bake request is outstanding. Do not overlap. bool mRerequestAppearanceBake; - boost::signals2::connection mBulkFecthCallbackSlot; /** * Lock for blocking operations on outfit until server reply or timeout exceed diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 4bca2ce650..32acd0eb03 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1764,11 +1764,19 @@ void LLInventoryModel::rebuildBrockenLinks() // make sure we aren't adding expensive Rebuild to anything else. notifyObservers(); - for (const LLUUID &link_id : mPossiblyBrockenLinks) + for (const broken_links_t::value_type &link_list : mPossiblyBrockenLinks) { - addChangedMask(LLInventoryObserver::REBUILD, link_id); + for (const LLUUID& link_id : link_list.second) + { + addChangedMask(LLInventoryObserver::REBUILD , link_id); + } + } + for (const LLUUID& link_id : mLinksRebuildList) + { + addChangedMask(LLInventoryObserver::REBUILD , link_id); } mPossiblyBrockenLinks.clear(); + mLinksRebuildList.clear(); notifyObservers(); } @@ -2075,6 +2083,20 @@ void LLInventoryModel::idleNotifyObservers() { // *FIX: Think I want this conditional or moved elsewhere... handleResponses(true); + + if (mLinksRebuildList.size() > 0) + { + if (mModifyMask != LLInventoryObserver::NONE || (mChangedItemIDs.size() != 0)) + { + notifyObservers(); + } + for (const LLUUID& link_id : mLinksRebuildList) + { + addChangedMask(LLInventoryObserver::REBUILD , link_id); + } + mLinksRebuildList.clear(); + notifyObservers(); + } if (mModifyMask == LLInventoryObserver::NONE && (mChangedItemIDs.size() == 0)) { @@ -2394,11 +2416,14 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) // The item will show up as a broken link. if (item->getIsBrokenLink()) { - if (LLInventoryModelBackgroundFetch::getInstance()->folderFetchActive()) + if (item->getAssetUUID().notNull() + && LLInventoryModelBackgroundFetch::getInstance()->folderFetchActive()) { - // isEverythingFetched is actually 'initial' fetch only. - // Schedule this link for a recheck once inventory gets loaded - mPossiblyBrockenLinks.insert(item->getUUID()); + // Schedule this link for a recheck as inventory gets loaded + // Todo: expand to cover not just an initial fetch + mPossiblyBrockenLinks[item->getAssetUUID()].insert(item->getUUID()); + + // Do a blank rebuild of links once fetch is done if (!mBulkFecthCallbackSlot.connected()) { // Links might take a while to update this way, and there @@ -2408,6 +2433,9 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) LLInventoryModelBackgroundFetch::getInstance()->setFetchCompletionCallback( [this]() { + // rebuild is just in case, primary purpose is to wipe + // the list since we won't be getting anything 'new' + // see mLinksRebuildList rebuildBrockenLinks(); mBulkFecthCallbackSlot.disconnect(); }); @@ -2424,6 +2452,16 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item) << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << LL_ENDL; } } + if (!mPossiblyBrockenLinks.empty()) + { + // check if we are waiting for this item + broken_links_t::iterator iter = mPossiblyBrockenLinks.find(item->getUUID()); + if (iter != mPossiblyBrockenLinks.end()) + { + mLinksRebuildList.insert(iter->second.begin() , iter->second.end()); + mPossiblyBrockenLinks.erase(iter); + } + } if (item->getIsLinkType()) { // Add back-link from linked-to UUID. diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index b506eaac62..db159d480a 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -580,7 +580,9 @@ private: U32 mModifyMaskBacklog; changed_items_t mChangedItemIDsBacklog; changed_items_t mAddedItemIDsBacklog; - changed_items_t mPossiblyBrockenLinks; + typedef std::map broken_links_t; + broken_links_t mPossiblyBrockenLinks; // there can be multiple links per item + changed_items_t mLinksRebuildList; boost::signals2::connection mBulkFecthCallbackSlot; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index f650cc383f..56646830a2 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -586,17 +586,15 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() curent_time = LLTimer::getTotalSeconds(); } - if (mRecursiveInventoryFetchStarted && mAllRecursiveFoldersFetched) + // Ideally we shouldn't fetch items if recursive fetch isn't done, + // but there is a chance some request will start timeouting and recursive + // fetch will get stuck on a signle folder, don't block item fetch in such case + while (!mFetchItemQueue.empty() && mFetchCount < max_concurrent_fetches && curent_time < end_time) { - // Don't fetch items if recursive fetch isn't done, - // it gets both items and folders and should get the items in question faster - while (!mFetchItemQueue.empty() && mFetchCount < max_concurrent_fetches && curent_time < end_time) - { - const FetchQueueInfo& fetch_info(mFetchItemQueue.front()); - bulkFetchViaAis(fetch_info); - mFetchItemQueue.pop_front(); - curent_time = LLTimer::getTotalSeconds(); - } + const FetchQueueInfo& fetch_info(mFetchItemQueue.front()); + bulkFetchViaAis(fetch_info); + mFetchItemQueue.pop_front(); + curent_time = LLTimer::getTotalSeconds(); } if (last_fetch_count != mFetchCount // if anything was added @@ -696,7 +694,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc item_type = AISAPI::LIBRARY; } - AISAPI::FetchCategoryChildren(cat_id , item_type , type == FT_RECURSIVE , cb); + AISAPI::FetchCategoryChildren(cat_id , item_type , type == FT_RECURSIVE , cb, 0); } } else diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index cd51a00c52..01ad4f0f09 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -579,6 +579,7 @@ LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& owner_id) : LLViewerInventoryCategory::LLViewerInventoryCategory(const LLViewerInventoryCategory* other) { copyViewerCategory(other); + mFetching = FETCH_NONE; } LLViewerInventoryCategory::~LLViewerInventoryCategory() -- cgit v1.3 From c3d22fba600a6c40268dfbec15ec1fe145cbbb1d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 13 Apr 2023 13:27:30 +0300 Subject: SL-19533 MacOS build fix --- indra/newview/llappearancemgr.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e160b5813f..9115d7e5c2 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -638,6 +638,11 @@ void LLBrokenLinkObserver::postProcess() { LLViewerInventoryItem* item = gInventory.getItem(mUUID); llassert(item && !item->getIsBrokenLink()); // the whole point was to get a correct link + if (item && item->getIsBrokenLink()) + { + LL_INFOS_ONCE("Avatar") << "Outfit link broken despite being regenerated" << LL_ENDL; + LL_DEBUGS("Avatar", "Inventory") << "Outfit link " << mUUID << " \"" << item->getName() << "\" is broken despite being regenerated" << LL_ENDL; + } LLAppearanceMgr::instance().updateAppearanceFromCOF( mEnforceItemRestrictions , -- cgit v1.3 From 154ab03bf8a5dacc3128718d1f15160f0cbe2b33 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Apr 2023 03:38:26 +0300 Subject: SL-19533 Special COF handling #2 --- indra/newview/llappearancemgr.cpp | 33 ++++++++++++++++------- indra/newview/llappearancemgr.h | 1 + indra/newview/llinventorymodelbackgroundfetch.cpp | 18 +------------ indra/newview/llinventorymodelbackgroundfetch.h | 5 ++-- indra/newview/llstartup.cpp | 3 +-- 5 files changed, 28 insertions(+), 32 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 9115d7e5c2..297403fc6c 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4561,18 +4561,31 @@ protected: nullary_func_t mCallable; }; +void callAfterCOFFetch(nullary_func_t cb) +{ + if (AISAPI::isAvailable()) + { + AISAPI::FetchCOF([cb](const LLUUID& id) { cb(); }); + } + else + { + LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); + callAfterCategoryFetch(cat_id, cb); + } +} + void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb) { - CallAfterCategoryFetchStage1 *stage1 = new CallAfterCategoryFetchStage1(cat_id, cb); - stage1->startFetch(); - if (stage1->isFinished()) - { - stage1->done(); - } - else - { - gInventory.addObserver(stage1); - } + CallAfterCategoryFetchStage1* stage1 = new CallAfterCategoryFetchStage1(cat_id, cb); + stage1->startFetch(); + if (stage1->isFinished()) + { + stage1->done(); + } + else + { + gInventory.addObserver(stage1); + } } void add_wearable_type_counts(const uuid_vec_t& ids, diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index cf953d21ac..f6aa30d865 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -338,6 +338,7 @@ public: LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& name); // Invoke a given callable after category contents are fully fetched. +void callAfterCOFFetch(nullary_func_t cb); void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb); // Wear all items in a uuid vector. diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index f56532ff8c..277ddb16ba 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -354,17 +354,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) void LLInventoryModelBackgroundFetch::scheduleFolderFetch(const LLUUID& cat_id, bool forced) { - if (AISAPI::isAvailable()) - { - if (mFetchFolderQueue.empty() || mFetchFolderQueue.back().mUUID != cat_id) - { - // On AIS make sure root goes to the top and follow up recursive - // fetches, not individual requests - mFetchFolderQueue.push_back(FetchQueueInfo(cat_id, forced ? FT_FORCED : FT_DEFAULT)); - gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); - } - } - else if (mFetchFolderQueue.empty() || mFetchFolderQueue.front().mUUID != cat_id) + if (mFetchFolderQueue.empty() || mFetchFolderQueue.front().mUUID != cat_id) { // Specific folder requests go to front of queue. mFetchFolderQueue.push_front(FetchQueueInfo(cat_id, forced ? FT_FORCED : FT_DEFAULT)); @@ -391,12 +381,6 @@ void LLInventoryModelBackgroundFetch::findLostItems() gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } -void LLInventoryModelBackgroundFetch::fetchCOF() -{ - // Will get COF folder, links in it and items those links point to - AISAPI::FetchCOF(); -} - void LLInventoryModelBackgroundFetch::setAllFoldersFetched() { if (mRecursiveInventoryFetchStarted && diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index db2d6db323..363d04486d 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -64,9 +64,8 @@ public: bool inventoryFetchCompleted() const; bool inventoryFetchInProgress() const; - void findLostItems(); - void fetchCOF(); - void incrFetchCount(S32 fetching); + void findLostItems(); + void incrFetchCount(S32 fetching); void incrFetchFolderCount(S32 fetching); bool isBulkFetchProcessingComplete() const; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 161beaff19..3a96a7bced 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1898,7 +1898,6 @@ bool idle_startup() } LLInventoryModelBackgroundFetch::instance().start(); - LLInventoryModelBackgroundFetch::instance().fetchCOF(); gInventory.createCommonSystemCategories(); // It's debatable whether this flag is a good idea - sets all @@ -2161,7 +2160,7 @@ bool idle_startup() gAgentWearables.notifyLoadingStarted(); gAgent.setOutfitChosen(TRUE); gAgentWearables.sendDummyAgentWearablesUpdate(); - callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), set_flags_and_update_appearance); + callAfterCOFFetch(set_flags_and_update_appearance); } display_startup(); -- cgit v1.3 From c1a3c7b239dcde347403c818d4ad1eeedf45d280 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Apr 2023 13:51:23 +0300 Subject: SL-19533 Special COF handling #3 --- indra/newview/llappearancemgr.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 297403fc6c..d79525ec62 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4563,13 +4563,16 @@ protected: void callAfterCOFFetch(nullary_func_t cb) { - if (AISAPI::isAvailable()) + LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN && AISAPI::isAvailable()) { + // Assume that we have no relevant cache. Fetch cof, and items cof's links point to. AISAPI::FetchCOF([cb](const LLUUID& id) { cb(); }); } else { - LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); + // Assume that cache is present. Process like a normal folder. callAfterCategoryFetch(cat_id, cb); } } -- cgit v1.3 From 697d3be3c9906a6d578a961710fc43816b6adeae Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 27 Apr 2023 01:30:57 +0300 Subject: SL-19533 Implement subset variant of children request --- indra/newview/llaisapi.cpp | 158 ++++++++++++++---- indra/newview/llaisapi.h | 13 +- indra/newview/llappearancemgr.cpp | 13 +- indra/newview/llinventorymodelbackgroundfetch.cpp | 195 +++++++++++++++++++--- indra/newview/llinventorymodelbackgroundfetch.h | 6 +- 5 files changed, 320 insertions(+), 65 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 6d13a06c54..c17b246ef1 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -51,6 +51,10 @@ std::list AISAPI::sPostponedQuery; const S32 MAX_SIMULTANEOUS_COROUTINES = 2048; +// AIS3 allows '*' requests, but in reality those will be cut at some point +// Specify own depth to be able to anticipate it and mark folders as incomplete +const S32 MAX_FOLDER_DEPTH_REQUEST = 50; + //------------------------------------------------------------------------- /*static*/ bool AISAPI::isAvailable() @@ -458,11 +462,11 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec { // can specify depth=*, but server side is going to cap requests // and reject everything 'over the top',. - depth = 50; + depth = MAX_FOLDER_DEPTH_REQUEST; } else { - depth = llmin(depth, 50); + depth = llmin(depth, MAX_FOLDER_DEPTH_REQUEST); } url += "?depth=" + std::to_string(depth); @@ -511,11 +515,11 @@ void AISAPI::FetchCategoryChildren(const std::string &identifier, bool recursive { // can specify depth=*, but server side is going to cap requests // and reject everything 'over the top',. - depth = 50; + depth = MAX_FOLDER_DEPTH_REQUEST; } else { - depth = llmin(depth, 50); + depth = llmin(depth, MAX_FOLDER_DEPTH_REQUEST); } url += "?depth=" + std::to_string(depth); @@ -562,11 +566,11 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r { // can specify depth=*, but server side is going to cap requests // and reject everything 'over the top',. - depth = 50; + depth = MAX_FOLDER_DEPTH_REQUEST; } else { - depth = llmin(depth, 50); + depth = llmin(depth, MAX_FOLDER_DEPTH_REQUEST); } url += "?depth=" + std::to_string(depth); @@ -592,6 +596,83 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r EnqueueAISCommand("FetchCategoryCategories", proc); } +void AISAPI::FetchCategorySubset(const LLUUID& catId, + const uuid_vec_t specificChildren, + ITEM_TYPE type, + bool recursive, + completion_t callback, + S32 depth) +{ + std::string cap = (type == INVENTORY) ? getInvCap() : getLibCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } + return; + } + if (specificChildren.empty()) + { + LL_WARNS("Inventory") << "Empty request!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } + return; + } + // category/any_folder_id/children?depth=*&children=child_id1,child_id2,child_id3 + std::string url = cap + std::string("/category/") + catId.asString() + "/children"; + + if (recursive) + { + depth = MAX_FOLDER_DEPTH_REQUEST; + } + else + { + depth = llmin(depth, MAX_FOLDER_DEPTH_REQUEST); + } + + uuid_vec_t::const_iterator iter = specificChildren.begin(); + uuid_vec_t::const_iterator end = specificChildren.end(); + + url += "?depth=" + std::to_string(depth) + "&children=" + iter->asString(); + iter++; + + while (iter != end) + { + url += "," + iter->asString(); + iter++; + } + + const S32 MAX_URL_LENGH = 2000; // RFC documentation specifies a maximum length of 2048 + if (url.length() > MAX_URL_LENGH) + { + LL_WARNS("Inventory") << "Request url is too long, url: " << url << LL_ENDL; + } + + invokationFn_t getFn = boost::bind( + // Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload. + static_cast + //---- + // _1 -> httpAdapter + // _2 -> httpRequest + // _3 -> url + // _4 -> body + // _5 -> httpOptions + // _6 -> httpHeaders + (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _5, _6); + + // get doesn't use body, can pass additional data + LLSD body; + body["depth"] = depth; + LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro, + _1, getFn, url, catId, body, callback, FETCHCATEGORYSUBSET)); + + EnqueueAISCommand("FetchCategorySubset", proc); +} + /*static*/ // Will get COF folder, links in it and items those links point to void AISAPI::FetchCOF(completion_t callback) @@ -710,7 +791,7 @@ void AISAPI::onIdle(void *userdata) } /*static*/ -void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type, const LLSD& request_body) +void AISAPI::onUpdateReceived(const LLSD& update, COMMAND_TYPE type, const LLSD& request_body) { LLTimer timer; if ( (type == UPDATECATEGORY || type == UPDATEITEM) @@ -718,18 +799,8 @@ void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, CO { dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); } - bool is_fetch = (type == FETCHITEM) - || (type == FETCHCATEGORYCHILDREN) - || (type == FETCHCATEGORYCATEGORIES) - || (type == FETCHCOF) - || (type == FETCHORPHANS); - // parse update llsd into stuff to do or parse received items. - S32 depth = 0; - if (is_fetch && request_body.has("depth")) - { - depth = request_body["depth"].asInteger(); - } - AISUpdate ais_update(update, is_fetch, depth); + + AISUpdate ais_update(update, type, request_body); ais_update.doUpdate(); // execute the updates in the appropriate order. LL_DEBUGS("Inventory", "AIS3") << "Elapsed processing: " << timer.getElapsedTimeF32() << LL_ENDL; } @@ -833,7 +904,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } LL_DEBUGS("Inventory", "AIS3") << "Result: " << result << LL_ENDL; - onUpdateReceived("AISCommand", result, type, body); + onUpdateReceived(result, type, body); if (callback && !callback.empty()) { @@ -900,10 +971,22 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } //------------------------------------------------------------------------- -AISUpdate::AISUpdate(const LLSD& update, bool fetch, S32 depth) -: mFetch(fetch) -, mFetchDepth(depth) +AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& request_body) +: mType(type) { + mFetch = (type == AISAPI::FETCHITEM) + || (type == AISAPI::FETCHCATEGORYCHILDREN) + || (type == AISAPI::FETCHCATEGORYCATEGORIES) + || (type == AISAPI::FETCHCATEGORYSUBSET) + || (type == AISAPI::FETCHCOF) + || (type == AISAPI::FETCHORPHANS); + // parse update llsd into stuff to do or parse received items. + mFetchDepth = MAX_FOLDER_DEPTH_REQUEST; + if (mFetch && request_body.has("depth")) + { + mFetchDepth = request_body["depth"].asInteger(); + } + mTimer.setTimerExpirySec(debugLoggingEnabled("Inventory") ? EXPIRY_SECONDS_DEBUG : EXPIRY_SECONDS_LIVE); mTimer.start(); parseUpdate(update); @@ -1023,17 +1106,26 @@ void AISUpdate::parseContent(const LLSD& update) { if (update.has("linked_id")) { - parseLink(update); + parseLink(update, mFetchDepth); } else if (update.has("item_id")) { parseItem(update); } - if (update.has("category_id")) - { - parseCategory(update, mFetchDepth); - } + if (mType == AISAPI::FETCHCATEGORYSUBSET) + { + // initial category is incomplete, don't process it, + // go for content instead + if (update.has("_embedded")) + { + parseEmbedded(update["_embedded"], mFetchDepth - 1); + } + } + else if (update.has("category_id")) + { + parseCategory(update, mFetchDepth); + } else { if (update.has("_embedded")) @@ -1089,7 +1181,7 @@ void AISUpdate::parseItem(const LLSD& item_map) } } -void AISUpdate::parseLink(const LLSD& link_map) +void AISUpdate::parseLink(const LLSD& link_map, S32 depth) { LLUUID item_id = link_map["item_id"].asUUID(); LLPointer new_link(new LLViewerInventoryItem); @@ -1145,7 +1237,7 @@ void AISUpdate::parseLink(const LLSD& link_map) if (link_map.has("_embedded")) { - parseEmbedded(link_map["_embedded"], S32_MAX); + parseEmbedded(link_map["_embedded"], depth); } } else @@ -1295,7 +1387,7 @@ void AISUpdate::parseEmbedded(const LLSD& embedded, S32 depth) if (embedded.has("links")) // _embedded in a category { - parseEmbeddedLinks(embedded["links"]); + parseEmbeddedLinks(embedded["links"], depth); } if (embedded.has("items")) // _embedded in a category { @@ -1328,7 +1420,7 @@ void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uui } } -void AISUpdate::parseEmbeddedLinks(const LLSD& links) +void AISUpdate::parseEmbeddedLinks(const LLSD& links, S32 depth) { for(LLSD::map_const_iterator linkit = links.beginMap(), linkend = links.endMap(); @@ -1342,7 +1434,7 @@ void AISUpdate::parseEmbeddedLinks(const LLSD& links) } else { - parseLink(link_map); + parseLink(link_map, depth); } } } diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 6afbbbd16e..691c5db592 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -59,11 +59,11 @@ public: static void FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); static void FetchCategoryChildren(const std::string &identifier, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); static void FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); + static void FetchCategorySubset(const LLUUID& catId, const uuid_vec_t specificChildren, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); static void FetchCOF(completion_t callback = completion_t()); static void FetchOrphans(completion_t callback = completion_t() ); static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t()); -private: typedef enum { COPYINVENTORY, SLAMFOLDER, @@ -77,10 +77,12 @@ private: FETCHITEM, FETCHCATEGORYCHILDREN, FETCHCATEGORYCATEGORIES, + FETCHCATEGORYSUBSET, FETCHCOF, FETCHORPHANS, } COMMAND_TYPE; +private: static const std::string INVENTORY_CAP_NAME; static const std::string LIBRARY_CAP_NAME; @@ -89,7 +91,7 @@ private: static void EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc); static void onIdle(void *userdata); // launches postponed AIS commands - static void onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type, const LLSD& request_body); + static void onUpdateReceived(const LLSD& update, COMMAND_TYPE type, const LLSD& request_body); static std::string getInvCap(); static std::string getLibCap(); @@ -105,17 +107,17 @@ private: class AISUpdate { public: - AISUpdate(const LLSD& update, bool fetch, S32 depth); + AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& request_body); void parseUpdate(const LLSD& update); void parseMeta(const LLSD& update); void parseContent(const LLSD& update); void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids); - void parseLink(const LLSD& link_map); + void parseLink(const LLSD& link_map, S32 depth); void parseItem(const LLSD& link_map); void parseCategory(const LLSD& link_map, S32 depth); void parseDescendentCount(const LLUUID& category_id, const LLSD& embedded); void parseEmbedded(const LLSD& embedded, S32 depth); - void parseEmbeddedLinks(const LLSD& links); + void parseEmbeddedLinks(const LLSD& links, S32 depth); void parseEmbeddedItems(const LLSD& items); void parseEmbeddedCategories(const LLSD& categories, S32 depth); void parseEmbeddedItem(const LLSD& item); @@ -151,6 +153,7 @@ private: bool mFetch; S32 mFetchDepth; LLTimer mTimer; + AISAPI::COMMAND_TYPE mType; }; #endif diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index d79525ec62..4133470973 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4568,7 +4568,18 @@ void callAfterCOFFetch(nullary_func_t cb) if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN && AISAPI::isAvailable()) { // Assume that we have no relevant cache. Fetch cof, and items cof's links point to. - AISAPI::FetchCOF([cb](const LLUUID& id) { cb(); }); + AISAPI::FetchCOF([cb](const LLUUID& id) + { + cb(); + LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); + LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); + if (cat) + { + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + } + }); + // Mark it so that background fetch won't request it if it didn't already + cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); } else { diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index c5fb40409f..b8fdfab98a 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -299,7 +299,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) // Not only root folder can be massive, but // most system folders will be requested independently // so request root folder and content separately - mFetchFolderQueue.push_front(FetchQueueInfo(gInventory.getRootFolderID(), FT_CONTENT_RECURSIVE)); + mFetchFolderQueue.push_front(FetchQueueInfo(gInventory.getRootFolderID(), FT_FOLDER_AND_CONTENT)); } else { @@ -455,10 +455,67 @@ void ais_simple_item_callback(const LLUUID& inv_id) LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } -void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType recursion) +void LLInventoryModelBackgroundFetch::onAISContentCalback( + const LLUUID& request_id, + const uuid_vec_t& content_ids, + const LLUUID& response_id, + EFetchType fetch_type) { + // Don't push_front on failure - there is a chance it was fired from inside bulkFetchViaAis incrFetchFolderCount(-1); - std::list::const_iterator found = std::find(mExpectedFolderIds.begin() , mExpectedFolderIds.end(), request_id); + + uuid_vec_t::const_iterator folder_iter = content_ids.begin(); + uuid_vec_t::const_iterator folder_end = content_ids.end(); + while (folder_iter != folder_end) + { + std::list::const_iterator found = std::find(mExpectedFolderIds.begin(), mExpectedFolderIds.end(), *folder_iter); + if (found != mExpectedFolderIds.end()) + { + mExpectedFolderIds.erase(found); + } + + LLViewerInventoryCategory* cat(gInventory.getCategory(*folder_iter)); + if (cat) + { + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + } + if (response_id.isNull()) + { + // Failed to fetch, get it individually + mFetchFolderQueue.push_back(FetchQueueInfo(*folder_iter, FT_RECURSIVE)); + } + else + { + // push descendant back to verify they are fetched fully (ex: didn't encounter depth limit) + LLInventoryModel::cat_array_t* categories(NULL); + LLInventoryModel::item_array_t* items(NULL); + gInventory.getDirectDescendentsOf(*folder_iter, categories, items); + if (categories) + { + for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); + it != categories->end(); + ++it) + { + mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE)); + } + } + } + + folder_iter++; + } + + if (!mFetchFolderQueue.empty()) + { + mBackgroundFetchActive = true; + mFolderFetchActive = true; + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + } +} +void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType fetch_type) +{ + // Don't push_front on failure - there is a chance it was fired from inside bulkFetchViaAis + incrFetchFolderCount(-1); + std::list::const_iterator found = std::find(mExpectedFolderIds.begin(), mExpectedFolderIds.end(), request_id); if (found != mExpectedFolderIds.end()) { mExpectedFolderIds.erase(found); @@ -480,32 +537,34 @@ void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_i if (response_id.isNull()) // Failure { LL_DEBUGS(LOG_INV , "AIS3") << "Failure response for folder " << request_id << LL_ENDL; - if (recursion == FT_RECURSIVE) + if (fetch_type == FT_RECURSIVE) { // A full recursive request failed. // Try requesting folder and nested content separately - mBackgroundFetchActive = true; - mFolderFetchActive = true; - mFetchFolderQueue.push_front(FetchQueueInfo(request_id, FT_CONTENT_RECURSIVE)); - gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + mFetchFolderQueue.push_back(FetchQueueInfo(request_id, FT_FOLDER_AND_CONTENT)); } - else if (recursion == FT_CONTENT_RECURSIVE) + else if (fetch_type == FT_FOLDER_AND_CONTENT) { LL_WARNS() << "Failed to download folder: " << request_id << " Requesting known content separately" << LL_ENDL; - request_descendants = true; + mFetchFolderQueue.push_back(FetchQueueInfo(request_id, FT_CONTENT_RECURSIVE)); } } else { - if (recursion == FT_CONTENT_RECURSIVE || recursion == FT_RECURSIVE) + if (fetch_type == FT_RECURSIVE) { - // Got the folder, now recursively request content + // Got the folder and content, now verify content // Request content even for FT_RECURSIVE in case of changes, failures // or if depth limit gets imlemented. // This shouldn't redownload folders if they already have version request_descendants = true; LL_DEBUGS(LOG_INV, "AIS3") << "Got folder " << request_id << ". Requesting content" << LL_ENDL; } + else if (fetch_type == FT_FOLDER_AND_CONTENT) + { + // readd folder for content request + mFetchFolderQueue.push_front(FetchQueueInfo(request_id, FT_CONTENT_RECURSIVE)); + } else { LL_DEBUGS(LOG_INV, "AIS3") << "Got folder " << request_id << "." << LL_ENDL; @@ -524,17 +583,18 @@ void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_i it != categories->end(); ++it) { - mFetchFolderQueue.push_front(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE)); - } - if (!mFetchFolderQueue.empty()) - { - mBackgroundFetchActive = true; - mFolderFetchActive = true; - gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE)); } } } + if (!mFetchFolderQueue.empty()) + { + mBackgroundFetchActive = true; + mFolderFetchActive = true; + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + } + // done LLViewerInventoryCategory * cat(gInventory.getCategory(request_id)); if (cat) @@ -555,9 +615,9 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() } static LLCachedControl ais_pool(gSavedSettings, "PoolSizeAIS", 20); - // Don't have too many requests at once + // Don't have too many requests at once, AIS throttles // Reserve one request for actions outside of fetch (like renames) - const U32 max_concurrent_fetches = llmax(1, ais_pool - 1); + const U32 max_concurrent_fetches = llclamp(ais_pool - 1, 1, 50); if (mFetchCount >= max_concurrent_fetches) { @@ -663,10 +723,97 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); if (cat) { - if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion() || fetch_info.mFetchType == FT_FORCED) + if (fetch_info.mFetchType == FT_CONTENT_RECURSIVE) + { + // fetch content only, ignore cat itself + uuid_vec_t children; + LLInventoryModel::cat_array_t* categories(NULL); + LLInventoryModel::item_array_t* items(NULL); + gInventory.getDirectDescendentsOf(cat_id, categories, items); + + LLViewerInventoryCategory::EFetchType target_state = + fetch_info.mFetchType > FT_CONTENT_RECURSIVE + ? LLViewerInventoryCategory::FETCH_RECURSIVE + : LLViewerInventoryCategory::FETCH_NORMAL; + // technically limit is 'as many as you can put into url', but for now stop at 10 + const S32 batch_limit = 10; + bool content_done = true; + + for (LLInventoryModel::cat_array_t::iterator it = categories->begin(); + it != categories->end(); + ++it) + { + LLViewerInventoryCategory* child_cat = (*it); + if (LLViewerInventoryCategory::VERSION_UNKNOWN != child_cat->getVersion() + || child_cat->getFetching() >= target_state) + { + // push it back to verify everything inside is fetched + mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE)); + continue; + } + + if (child_cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_LISTINGS) + { + // special case + content_done = false; + if (children.empty()) + { + // fetch marketplace alone + children.push_back(child_cat->getUUID()); + mExpectedFolderIds.push_back(child_cat->getUUID()); + child_cat->setFetching(target_state); + break; + } + else + { + // fetch marketplace alone next run + continue; + } + } + + children.push_back(child_cat->getUUID()); + mExpectedFolderIds.push_back(child_cat->getUUID()); + child_cat->setFetching(target_state); + + if (children.size() >= batch_limit) + { + content_done = false; + break; + } + } + + if (!children.empty()) + { + // increment before call in case of immediate callback + incrFetchFolderCount(1); + + EFetchType type = fetch_info.mFetchType; + LLUUID cat_id = cat->getUUID(); // need a copy for lambda + AISAPI::completion_t cb = [cat_id, children, type](const LLUUID& response_id) + { + LLInventoryModelBackgroundFetch::instance().onAISContentCalback(cat_id, children, response_id, type); + }; + + AISAPI::ITEM_TYPE item_type = AISAPI::INVENTORY; + if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) + { + item_type = AISAPI::LIBRARY; + } + + AISAPI::FetchCategorySubset(cat_id, children, item_type, true, cb, 0); + } + + if (!content_done) + { + // send it back to get the rest + mFetchFolderQueue.push_back(FetchQueueInfo(cat_id, FT_CONTENT_RECURSIVE)); + } + } + else if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion() + || fetch_info.mFetchType == FT_FORCED) { LLViewerInventoryCategory::EFetchType target_state = - fetch_info.mFetchType >= FT_CONTENT_RECURSIVE + fetch_info.mFetchType > FT_CONTENT_RECURSIVE ? LLViewerInventoryCategory::FETCH_RECURSIVE : LLViewerInventoryCategory::FETCH_NORMAL; // start again if we did a non-recursive fetch before @@ -711,7 +858,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc } } } - } // else? + } // else try to fetch folder either way? } } else diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 363d04486d..1fd7426312 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -82,8 +82,9 @@ protected: typedef enum { FT_DEFAULT = 0, - FT_FORCED, // request even if already loaded + FT_FORCED, // request non-recursively even if already loaded FT_CONTENT_RECURSIVE, // request content recursively + FT_FOLDER_AND_CONTENT, // request content recursively FT_RECURSIVE, // request everything recursively } EFetchType; struct FetchQueueInfo @@ -100,7 +101,8 @@ protected: }; typedef std::deque fetch_queue_t; - void onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType recursion); + void onAISContentCalback(const LLUUID& request_id, const uuid_vec_t &content_ids, const LLUUID& response_id, EFetchType fetch_type); + void onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType fetch_type); void bulkFetchViaAis(); void bulkFetchViaAis(const FetchQueueInfo& fetch_info); void bulkFetch(); -- cgit v1.3 From 98681ef73ff33e0c0ff321e839a8e79b2cb334de Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 5 May 2023 15:56:21 +0300 Subject: SL-19533 Prevent COF dupplicate request --- indra/newview/llappearancemgr.cpp | 20 +++++++++++++++----- indra/newview/llinventorymodel.cpp | 13 +++++++++++-- indra/newview/llstartup.cpp | 14 +++++++++++++- 3 files changed, 39 insertions(+), 8 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 4133470973..454ac5d88c 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4565,10 +4565,14 @@ void callAfterCOFFetch(nullary_func_t cb) { LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN && AISAPI::isAvailable()) + if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) { - // Assume that we have no relevant cache. Fetch cof, and items cof's links point to. - AISAPI::FetchCOF([cb](const LLUUID& id) + if (AISAPI::isAvailable()) + { + // Mark cof (update timer) so that background fetch won't request it + cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + // Assume that we have no relevant cache. Fetch cof, and items cof's links point to. + AISAPI::FetchCOF([cb](const LLUUID& id) { cb(); LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); @@ -4578,8 +4582,14 @@ void callAfterCOFFetch(nullary_func_t cb) cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); } }); - // Mark it so that background fetch won't request it if it didn't already - cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + } + else + { + LL_WARNS() << "AIS API v3 not available, can't use AISAPI::FetchCOF" << LL_ENDL; + // startup should have marked folder as fetching, remove that + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + callAfterCategoryFetch(cat_id, cb); + } } else { diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 48539f4748..c65901a754 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -853,8 +853,17 @@ void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred LLStringUtil::null, [preferred_type](const LLUUID &new_cat_id) { - LL_DEBUGS("Inventory") << "Created category: " << new_cat_id - << " for type: " << preferred_type << LL_ENDL; + if (new_cat_id.isNull()) + { + LL_WARNS("Inventory") + << "Failed to create folder of type " << preferred_type + << LL_ENDL; + } + else + { + LL_DEBUGS("Inventory") << "Created category: " << new_cat_id + << " for type: " << preferred_type << LL_ENDL; + } } ); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 5d1df21c9b..10ddd59f34 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1900,9 +1900,21 @@ bool idle_startup() LLNotificationsUtil::add("InventoryUnusable"); } - LLInventoryModelBackgroundFetch::instance().start(); gInventory.createCommonSystemCategories(); + LLInventoryModelBackgroundFetch::instance().start(); + LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); + if (cof + && cof->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + // Special case, dupplicate request prevention. + // Cof folder will be requested via FetchCOF + // in appearance manager, prevent recursive fetch + cof->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + } + + // It's debatable whether this flag is a good idea - sets all // bits, and in general it isn't true that inventory // initialization generates all types of changes. Maybe add an -- cgit v1.3 From 3058e6e6fd66ad4abb91fa5354ee11f6b7843a02 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 19 Jul 2023 21:15:52 +0300 Subject: SL-20015 wait for the outfit items to load before wearing it --- indra/newview/llaisapi.cpp | 36 ++++++++++++++++++++++++++++++++++++ indra/newview/llaisapi.h | 2 ++ indra/newview/llappearancemgr.cpp | 29 +++++++++++++++++++++++++++++ indra/newview/llappearancemgr.h | 1 + indra/newview/llinventorymodel.cpp | 12 +++++++++++- indra/newview/llinventorymodel.h | 4 ++++ indra/newview/llstartup.cpp | 25 ++++++++++++++++++++++++- indra/newview/llstartup.h | 1 + 8 files changed, 108 insertions(+), 2 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 4ac2acf1d1..f3799361db 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -709,6 +709,40 @@ void AISAPI::FetchCOF(completion_t callback) EnqueueAISCommand("FetchCOF", proc); } +void AISAPI::FetchCategoryLinks(const LLUUID &catId, completion_t callback) +{ + std::string cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } + return; + } + std::string url = cap + std::string("/category/") + catId.asString() + "/links"; + + invokationFn_t getFn = boost::bind( + // Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload. + static_cast + //---- + // _1 -> httpAdapter + // _2 -> httpRequest + // _3 -> url + // _4 -> body + // _5 -> httpOptions + // _6 -> httpHeaders + (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), + _1, _2, _3, _5, _6); + + LLCoprocedureManager::CoProcedure_t proc( + boost::bind(&AISAPI::InvokeAISCommandCoro, _1, getFn, url, LLUUID::null, LLSD(), callback, FETCHCATEGORYLINKS)); + + EnqueueAISCommand("FetchCategoryLinks", proc); +} + /*static*/ void AISAPI::FetchOrphans(completion_t callback) { @@ -938,6 +972,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht case FETCHCATEGORYCATEGORIES: case FETCHCATEGORYCHILDREN: case FETCHCATEGORYSUBSET: + case FETCHCATEGORYLINKS: case FETCHCOF: if (result.has("category_id")) { @@ -1002,6 +1037,7 @@ AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& || (type == AISAPI::FETCHCATEGORYCATEGORIES) || (type == AISAPI::FETCHCATEGORYSUBSET) || (type == AISAPI::FETCHCOF) + || (type == AISAPI::FETCHCATEGORYLINKS) || (type == AISAPI::FETCHORPHANS); // parse update llsd into stuff to do or parse received items. mFetchDepth = MAX_FOLDER_DEPTH_REQUEST; diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 973c82a847..53c74ae078 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -62,6 +62,7 @@ public: static void FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); static void FetchCategorySubset(const LLUUID& catId, const uuid_vec_t specificChildren, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0); static void FetchCOF(completion_t callback = completion_t()); + static void FetchCategoryLinks(const LLUUID &catId, completion_t callback = completion_t()); static void FetchOrphans(completion_t callback = completion_t() ); static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t()); @@ -81,6 +82,7 @@ public: FETCHCATEGORYSUBSET, FETCHCOF, FETCHORPHANS, + FETCHCATEGORYLINKS } COMMAND_TYPE; private: diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 454ac5d88c..d4fc6a9f9d 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4612,6 +4612,35 @@ void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb) } } +void callAfterCategoryLinksFetch(const LLUUID &cat_id, nullary_func_t cb) +{ + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + if (AISAPI::isAvailable()) + { + // Mark folder (update timer) so that background fetch won't request it + cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + // Assume that we have no relevant cache. Fetch folder, and items folder's links point to. + AISAPI::FetchCategoryLinks(cat_id, + [cb, cat_id](const LLUUID &id) + { + cb(); + LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); + if (cat) + { + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + } + }); + } + else + { + LL_WARNS() << "AIS API v3 not available, can't use AISAPI::FetchCOF" << LL_ENDL; + // startup should have marked folder as fetching, remove that + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + callAfterCategoryFetch(cat_id, cb); + } + +} + void add_wearable_type_counts(const uuid_vec_t& ids, S32& clothing_count, S32& bodypart_count, diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index f6aa30d865..43839e47a6 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -340,6 +340,7 @@ LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string& // Invoke a given callable after category contents are fully fetched. void callAfterCOFFetch(nullary_func_t cb); void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb); +void callAfterCategoryLinksFetch(const LLUUID &cat_id, nullary_func_t cb); // Wear all items in a uuid vector. void wear_multiple(const uuid_vec_t& ids, bool replace); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ed375661b8..586f1388ff 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -79,6 +79,8 @@ const S32 LLInventoryModel::sCurrentInvCacheVersion = 3; BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE; +S32 LLInventoryModel::sPendingSystemFolders = 0; + ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- @@ -861,8 +863,9 @@ void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred } else { - LL_DEBUGS("Inventory") << "Created category: " << new_cat_id + LL_WARNS("Inventory") << "Created category: " << new_cat_id << " for type: " << preferred_type << LL_ENDL; + sPendingSystemFolders--; } } ); @@ -873,6 +876,10 @@ void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred << " because inventory is not usable" << LL_ENDL; } } + else + { + sPendingSystemFolders--; + } } const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot( @@ -3253,6 +3260,9 @@ LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground, void LLInventoryModel::createCommonSystemCategories() { + //amount of System Folder we should wait for + sPendingSystemFolders = 8; + gInventory.ensureCategoryForTypeExists(LLFolderType::FT_TRASH); gInventory.ensureCategoryForTypeExists(LLFolderType::FT_FAVORITE); gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CALLINGCARD); diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index db159d480a..a90ed2bf42 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -227,10 +227,14 @@ private: //-------------------------------------------------------------------- public: static BOOL getIsFirstTimeInViewer2(); + static bool isSysFoldersReady() { return (sPendingSystemFolders == 0); } + private: static BOOL sFirstTimeInViewer2; const static S32 sCurrentInvCacheVersion; // expected inventory cache version + static S32 sPendingSystemFolders; + /** Initialization/Setup ** ** *******************************************************************************/ diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 9f9e117760..c925563919 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1912,7 +1912,22 @@ bool idle_startup() LLInventoryModelBackgroundFetch::instance().start(); gInventory.createCommonSystemCategories(); + LLStartUp::setStartupState(STATE_INVENTORY_CALLBACKS ); + display_startup(); + + return FALSE; + } + //--------------------------------------------------------------------- + // STATE_INVENTORY_CALLBACKS + //--------------------------------------------------------------------- + if (STATE_INVENTORY_CALLBACKS == LLStartUp::getStartupState()) + { + if (!LLInventoryModel::isSysFoldersReady()) + { + display_startup(); + return FALSE; + } LLInventoryModelBackgroundFetch::instance().start(); LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id); @@ -2850,8 +2865,15 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name, bool do_append = false; LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id); // Need to fetch cof contents before we can wear. - callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), + if (do_copy) + { + callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(), boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); + } + else + { + callAfterCategoryLinksFetch(cat_id, boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append)); + } LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL; } @@ -2904,6 +2926,7 @@ std::string LLStartUp::startupStateToString(EStartupState state) RTNENUM( STATE_AGENT_SEND ); RTNENUM( STATE_AGENT_WAIT ); RTNENUM( STATE_INVENTORY_SEND ); + RTNENUM(STATE_INVENTORY_CALLBACKS ); RTNENUM( STATE_MISC ); RTNENUM( STATE_PRECACHE ); RTNENUM( STATE_WEARABLES_WAIT ); diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h index fe8e215f76..921f088423 100644 --- a/indra/newview/llstartup.h +++ b/indra/newview/llstartup.h @@ -71,6 +71,7 @@ typedef enum { STATE_AGENT_SEND, // Connect to a region STATE_AGENT_WAIT, // Wait for region STATE_INVENTORY_SEND, // Do inventory transfer + STATE_INVENTORY_CALLBACKS, // Wait for missing system folders and register callbacks STATE_MISC, // Do more things (set bandwidth, start audio, save location, etc) STATE_PRECACHE, // Wait a bit for textures to download STATE_WEARABLES_WAIT, // Wait for clothing to download -- cgit v1.3 From 6b5345eabd75e62b99333c51877b02e5a54f66d2 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 5 Aug 2023 17:36:38 +0300 Subject: SL-20120 Fix unneeded warnings - Don't Warn about unknown cof version, it's expected during fetch, Info is enough - Fix 'unexpected attachments' due to unknown cof, also should fix viewer trying to create a link before cof is ready - Fix 'accounting' warnings when getting item updates for unfetched folders (Note: viewer doesn't know folders version, if fetch is already in progress we might get an old version) --- indra/newview/llappearancemgr.cpp | 2 +- indra/newview/llattachmentsmgr.cpp | 6 ++++++ indra/newview/llinventorymodel.cpp | 43 ++++++++++++++++++++++++++++---------- 3 files changed, 39 insertions(+), 12 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index d4fc6a9f9d..6251737699 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3821,7 +3821,7 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd if (cofVersion == LLViewerInventoryCategory::VERSION_UNKNOWN) { - LL_WARNS("AVatar") << "COF version is unknown... not requesting until COF version is known." << LL_ENDL; + LL_INFOS("AVatar") << "COF version is unknown... not requesting until COF version is known." << LL_ENDL; return; } else diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index d43048a8b6..926cab403e 100644 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -239,6 +239,12 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments() return; } + if (LLAppearanceMgr::instance().getCOFVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + { + // Wait for cof to load + return; + } + LL_DEBUGS("Avatar") << "ATT checking COF linkability for " << mRecentlyArrivedAttachments.size() << " recently arrived items" << LL_ENDL; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 586f1388ff..aa750a19b0 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3788,15 +3788,22 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) LLViewerInventoryCategory* folderp = gInventory.getCategory(tfolder->getUUID()); if(folderp) { - if(tfolder->getParentUUID() == folderp->getParentUUID()) - { - update[tfolder->getParentUUID()]; - } - else - { - ++update[tfolder->getParentUUID()]; - --update[folderp->getParentUUID()]; - } + if (folderp->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN) + { + if (tfolder->getParentUUID() == folderp->getParentUUID()) + { + update[tfolder->getParentUUID()]; + } + else + { + ++update[tfolder->getParentUUID()]; + --update[folderp->getParentUUID()]; + } + } + else + { + folderp->fetch(); + } } else { @@ -3806,7 +3813,14 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) folderp = gInventory.getCategory(tfolder->getParentUUID()); if(folderp) { - ++update[tfolder->getParentUUID()]; + if (folderp->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN) + { + ++update[tfolder->getParentUUID()]; + } + else + { + folderp->fetch(); + } } } } @@ -3852,7 +3866,14 @@ void LLInventoryModel::processBulkUpdateInventory(LLMessageSystem* msg, void**) LLViewerInventoryCategory* folderp = gInventory.getCategory(titem->getParentUUID()); if(folderp) { - ++update[titem->getParentUUID()]; + if (folderp->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN) + { + ++update[titem->getParentUUID()]; + } + else + { + folderp->fetch(); + } } } } -- cgit v1.3 From fa47e4402b7925a45c5fec9fb9d92fb5e34a589e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 14 Sep 2023 18:42:42 +0300 Subject: SL-20285 Sturdier cof and fixed link fetching --- indra/newview/llaisapi.cpp | 62 +++++++++++++++++++---------------- indra/newview/llaisapi.h | 2 +- indra/newview/llappearancemgr.cpp | 58 ++++++++++++++++---------------- indra/newview/llattachmentsmgr.cpp | 1 + indra/newview/llinventoryobserver.cpp | 19 ++++------- 5 files changed, 70 insertions(+), 72 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index d8d30037c8..087cfb8d48 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -741,8 +741,10 @@ void AISAPI::FetchCategoryLinks(const LLUUID &catId, completion_t callback) (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _5, _6); + LLSD body; + body["depth"] = 0; LLCoprocedureManager::CoProcedure_t proc( - boost::bind(&AISAPI::InvokeAISCommandCoro, _1, getFn, url, LLUUID::null, LLSD(), callback, FETCHCATEGORYLINKS)); + boost::bind(&AISAPI::InvokeAISCommandCoro, _1, getFn, url, LLUUID::null, body, callback, FETCHCATEGORYLINKS)); EnqueueAISCommand("FetchCategoryLinks", proc); } @@ -1337,13 +1339,6 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) return; } - // Check descendent count first, as it may be needed - // to populate newly created categories - if (category_map.has("_embedded")) - { - parseDescendentCount(category_id, category_map["_embedded"]); - } - LLPointer new_cat; if (curr_cat) { @@ -1366,6 +1361,13 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) // *NOTE: unpackMessage does not unpack version or descendent count. if (rv) { + // Check descendent count first, as it may be needed + // to populate newly created categories + if (category_map.has("_embedded")) + { + parseDescendentCount(category_id, new_cat->getPreferredType(), category_map["_embedded"]); + } + if (mFetch) { uuid_int_map_t::const_iterator lookup_it = mCatDescendentsKnown.find(category_id); @@ -1379,10 +1381,20 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) // set version only if we are sure this update has full data and embeded items // since viewer uses version to decide if folder and content still need fetching if (version > LLViewerInventoryCategory::VERSION_UNKNOWN - && (depth >= 0 || (curr_cat && curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN))) + && depth >= 0) { - LL_DEBUGS("Inventory") << "Setting version to " << version - << " for category " << category_id << LL_ENDL; + if (curr_cat && curr_cat->getVersion() > version) + { + LL_WARNS("Inventory") << "Version was " << curr_cat->getVersion() + << ", but fetch returned version " << version + << " for category " << category_id << LL_ENDL; + } + else + { + LL_DEBUGS("Inventory") << "Setting version to " << version + << " for category " << category_id << LL_ENDL; + } + new_cat->setVersion(version); } } @@ -1445,27 +1457,21 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) } } -void AISUpdate::parseDescendentCount(const LLUUID& category_id, const LLSD& embedded) +void AISUpdate::parseDescendentCount(const LLUUID& category_id, LLFolderType::EType type, const LLSD& embedded) { - if (mType == AISAPI::FETCHCOF) + // We can only determine true descendent count if this contains all descendent types. + if (embedded.has("categories") && + embedded.has("links") && + embedded.has("items")) { - // contains only links - if (embedded.has("links")) - { - mCatDescendentsKnown[category_id] = embedded["links"].size(); - } + mCatDescendentsKnown[category_id] = embedded["categories"].size(); + mCatDescendentsKnown[category_id] += embedded["links"].size(); + mCatDescendentsKnown[category_id] += embedded["items"].size(); } - else + else if (mFetch && embedded.has("links") && (type == LLFolderType::FT_CURRENT_OUTFIT || type == LLFolderType::FT_OUTFIT)) { - // We can only determine true descendent count if this contains all descendent types. - if (embedded.has("categories") && - embedded.has("links") && - embedded.has("items")) - { - mCatDescendentsKnown[category_id] = embedded["categories"].size(); - mCatDescendentsKnown[category_id] += embedded["links"].size(); - mCatDescendentsKnown[category_id] += embedded["items"].size(); - } + // COF and outfits contain links only + mCatDescendentsKnown[category_id] = embedded["links"].size(); } } diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 53c74ae078..0fdf4a0b74 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -118,7 +118,7 @@ public: void parseLink(const LLSD& link_map, S32 depth); void parseItem(const LLSD& link_map); void parseCategory(const LLSD& link_map, S32 depth); - void parseDescendentCount(const LLUUID& category_id, const LLSD& embedded); + void parseDescendentCount(const LLUUID& category_id, LLFolderType::EType type, const LLSD& embedded); void parseEmbedded(const LLSD& embedded, S32 depth); void parseEmbeddedLinks(const LLSD& links, S32 depth); void parseEmbeddedItems(const LLSD& items); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 80ef5e3bae..876ae23e62 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4446,7 +4446,7 @@ public: { LLViewerInventoryCategory* cat = gInventory.getCategory(*it); if (!cat) continue; - if (!isCategoryComplete(cat)) + if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) { // CHECK IT: isCategoryComplete() checks both version and descendant count but // fetch() only works for Unknown version and doesn't care about descentants, @@ -4456,6 +4456,12 @@ public: cat->fetch(); //blindly fetch it without seeing if anything else is fetching it. mIncomplete.push_back(*it); //Add to list of things being downloaded for this observer. } + else if (!isCategoryComplete(cat)) + { + LL_DEBUGS("Inventory") << "Categoty " << *it << " incomplete despite having version" << LL_ENDL; + LLInventoryModelBackgroundFetch::instance().scheduleFolderFetch(*it, true); + mIncomplete.push_back(*it); + } else if (ais3) { LLInventoryModel::cat_array_t* cats; @@ -4484,10 +4490,7 @@ public: if (incomplete_count > MAX_INDIVIDUAL_FETCH || (incomplete_count > 1 && complete_count == 0)) { - // To prevent premature removal from mIncomplete and - // since we are doing a full refetch anyway, mark unknown - cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN); - cat->fetch(); + LLInventoryModelBackgroundFetch::instance().scheduleFolderFetch(*it, true); mIncomplete.push_back(*it); } else @@ -4496,6 +4499,7 @@ public: mComplete.push_back(*it); } } + // else should have been handled by isCategoryComplete } else { @@ -4519,13 +4523,11 @@ public: // What we do here is get the complete information on the // items in the requested category, and set up an observer // that will wait for that to happen. - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - gInventory.collectDescendents(mComplete.front(), - cat_array, - item_array, - LLInventoryModel::EXCLUDE_TRASH); - S32 count = item_array.size(); + LLInventoryModel::cat_array_t* cats; + LLInventoryModel::item_array_t* items; + gInventory.getDirectDescendentsOf(mComplete.front(), cats, items); + + S32 count = items->size(); if(!count) { LL_WARNS() << "Nothing fetched in category " << mComplete.front() @@ -4537,11 +4539,13 @@ public: return; } - LL_INFOS() << "stage1 got " << item_array.size() << " items, passing to stage2 " << LL_ENDL; + LLViewerInventoryCategory* cat = gInventory.getCategory(mComplete.front()); + S32 version = cat ? cat->getVersion() : -2; + LL_INFOS() << "stage1, category " << mComplete.front() << " got " << count << " items, version " << version << " passing to stage2 " << LL_ENDL; uuid_vec_t ids; for(S32 i = 0; i < count; ++i) { - ids.push_back(item_array.at(i)->getUUID()); + ids.push_back(items->at(i)->getUUID()); } gInventory.removeObserver(this); @@ -4570,14 +4574,14 @@ void callAfterCOFFetch(nullary_func_t cb) { LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) + + if (AISAPI::isAvailable()) { - if (AISAPI::isAvailable()) - { - // Mark cof (update timer) so that background fetch won't request it - cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); - // Assume that we have no relevant cache. Fetch cof, and items cof's links point to. - AISAPI::FetchCOF([cb](const LLUUID& id) + // Mark cof (update timer) so that background fetch won't request it + cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE); + // For reliability assume that we have no relevant cache, so + // fetch cof along with items cof's links point to. + AISAPI::FetchCOF([cb](const LLUUID& id) { cb(); LLUUID cat_id = LLAppearanceMgr::instance().getCOF(); @@ -4587,18 +4591,12 @@ void callAfterCOFFetch(nullary_func_t cb) cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); } }); - } - else - { - LL_WARNS() << "AIS API v3 not available, can't use AISAPI::FetchCOF" << LL_ENDL; - // startup should have marked folder as fetching, remove that - cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); - callAfterCategoryFetch(cat_id, cb); - } } else { - // Assume that cache is present. Process like a normal folder. + LL_INFOS() << "AIS API v3 not available, using callAfterCategoryFetch" << LL_ENDL; + // startup should have marked folder as fetching, remove that + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); callAfterCategoryFetch(cat_id, cb); } } diff --git a/indra/newview/llattachmentsmgr.cpp b/indra/newview/llattachmentsmgr.cpp index bcd89cf8db..d3fce306bc 100644 --- a/indra/newview/llattachmentsmgr.cpp +++ b/indra/newview/llattachmentsmgr.cpp @@ -243,6 +243,7 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments() if (LLAppearanceMgr::instance().getCOFVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN) { // Wait for cof to load + LL_DEBUGS_ONCE("Avatar") << "Received atachments, but cof isn't loaded yet, postponing processing" << LL_ENDL; return; } diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 227d4285eb..51be44bef4 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -334,21 +334,14 @@ void LLInventoryFetchItemsObserver::startFetch() if (aisv3) { - const S32 MAX_INDIVIDUAL_REQUESTS = 10; + const S32 MAX_INDIVIDUAL_REQUESTS = 7; for (requests_by_folders_t::value_type &folder : requests) { - LLViewerInventoryCategory* cat = gInventory.getCategory(folder.first); if (folder.second.size() > MAX_INDIVIDUAL_REQUESTS) { // requesting one by one will take a while // do whole folder - if (cat) - { - // Either drop version or use scheduleFolderFetch to force-fetch - // otherwise background fetch will ignore folders with set version - cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN); - } - LLInventoryModelBackgroundFetch::getInstance()->start(folder.first); + LLInventoryModelBackgroundFetch::getInstance()->scheduleFolderFetch(folder.first, true); } else { @@ -360,12 +353,11 @@ void LLInventoryFetchItemsObserver::startFetch() // start fetching whole folder since it's not ready either way cat->fetch(); } - else if (cat->getViewerDescendentCount() <= folder.second.size()) + else if (cat->getViewerDescendentCount() <= folder.second.size() + || cat->getDescendentCount() <= folder.second.size()) { // Start fetching whole folder since we need all items - // Drop version or use scheduleFolderFetch - cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN); - cat->fetch(); + LLInventoryModelBackgroundFetch::getInstance()->scheduleFolderFetch(folder.first, true); } else @@ -382,6 +374,7 @@ void LLInventoryFetchItemsObserver::startFetch() // Isn't supposed to happen? We should have all folders // and if item exists, folder is supposed to exist as well. llassert(false); + LL_WARNS("Inventory") << "Missing folder: " << folder.first << " fetching items individually" << LL_ENDL; // get items one by one for (LLUUID &item_id : folder.second) -- cgit v1.3 From b09c19d27ceb2a3695cd688b1ccffcb3084f0e46 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 14 Sep 2023 20:58:42 +0300 Subject: SL-20285 Updated individual request count declaration --- indra/newview/llappearancemgr.cpp | 3 +-- indra/newview/llinventoryobserver.cpp | 4 ++-- indra/newview/llinventoryobserver.h | 3 +++ 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'indra/newview/llappearancemgr.cpp') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 876ae23e62..8010b84c20 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4486,8 +4486,7 @@ public: // AIS can fetch couple items, but if there // is more than a dozen it will be very slow // it's faster to get whole folder in such case - const S32 MAX_INDIVIDUAL_FETCH = 10; - if (incomplete_count > MAX_INDIVIDUAL_FETCH + if (incomplete_count > LLInventoryFetchItemsObserver::MAX_INDIVIDUAL_ITEM_REQUESTS || (incomplete_count > 1 && complete_count == 0)) { LLInventoryModelBackgroundFetch::instance().scheduleFolderFetch(*it, true); diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 51be44bef4..281a8bc789 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -58,6 +58,7 @@ #include "llsdutil.h" #include +const S32 LLInventoryFetchItemsObserver::MAX_INDIVIDUAL_ITEM_REQUESTS = 7; const F32 LLInventoryFetchItemsObserver::FETCH_TIMER_EXPIRY = 60.0f; @@ -334,10 +335,9 @@ void LLInventoryFetchItemsObserver::startFetch() if (aisv3) { - const S32 MAX_INDIVIDUAL_REQUESTS = 7; for (requests_by_folders_t::value_type &folder : requests) { - if (folder.second.size() > MAX_INDIVIDUAL_REQUESTS) + if (folder.second.size() > MAX_INDIVIDUAL_ITEM_REQUESTS) { // requesting one by one will take a while // do whole folder diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 93109a70ac..bec08d2cdf 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -104,6 +104,9 @@ public: /*virtual*/ void startFetch(); /*virtual*/ void changed(U32 mask); + + // For attempts to group requests if too many items are requested + static const S32 MAX_INDIVIDUAL_ITEM_REQUESTS; private: LLTimer mFetchingPeriod; -- cgit v1.3