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 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'indra/newview/llaisapi.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); } } -- cgit v1.3 From ff6ff01c6a3822c8160279fecd3c3f2e636c4349 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 10 Mar 2023 00:12:16 +0200 Subject: SL-18629 Replacing UDP creation messages with callback based AIS --- indra/newview/llaisapi.cpp | 17 +- indra/newview/llfloatermarketplacelistings.cpp | 7 +- indra/newview/llinventorybridge.cpp | 131 +++++++++----- indra/newview/llinventoryfunctions.cpp | 229 ++++++++++++++++++------- indra/newview/llinventoryfunctions.h | 47 ++++- indra/newview/llinventorymodel.cpp | 110 ++++++------ indra/newview/llinventorymodel.h | 2 +- indra/newview/llmarketplacefunctions.cpp | 6 +- 8 files changed, 369 insertions(+), 180 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index d2c59cfaba..3826da0341 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -93,6 +93,7 @@ void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, c if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + callback(LLUUID::null); return; } @@ -485,13 +486,17 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht { LLUUID id(LLUUID::null); - if (result.has("category_id") && (type == COPYLIBRARYCATEGORY)) + if (type == COPYLIBRARYCATEGORY) { - id = result["category_id"]; + if (result.has("category_id")) + { + id = result["category_id"]; + } //else signal failure callback(id); } if (type == CREATEINVENTORY) { + bool informed_caller = false; if (result.has("_created_categories")) { LLSD& cats = result["_created_categories"]; @@ -500,6 +505,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht { LLUUID cat_id = *cat_iter; callback(cat_id); + informed_caller = true; } } if (result.has("_created_items")) @@ -510,8 +516,15 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht { LLUUID item_id = *item_iter; callback(item_id); + informed_caller = true; } } + + if (!informed_caller) + { + // signal failure with null id + callback(id); + } } } diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp index 9110d9e902..b547150b56 100644 --- a/indra/newview/llfloatermarketplacelistings.cpp +++ b/indra/newview/llfloatermarketplacelistings.cpp @@ -896,8 +896,11 @@ void LLFloaterMarketplaceValidation::onOpen(const LLSD& key) // Validates the folder if (cat_id.notNull()) { - LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); - validate_marketplacelistings(cat, boost::bind(&LLFloaterMarketplaceValidation::appendMessage, this, _1, _2, _3), false); + LLMarketplaceValidator::getInstance()->validateMarketplaceListings( + cat_id, + NULL, + boost::bind(&LLFloaterMarketplaceValidation::appendMessage, this, _1, _2, _3), + false); } // Handle the listing folder being processed diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index fb92437c3d..b4d7762613 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2901,11 +2901,16 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid); if (version_folder_id.notNull()) { - LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id); - if (!validate_marketplacelistings(cat,NULL)) + LLMarketplaceValidator::getInstance()->validateMarketplaceListings( + version_folder_id, + [version_folder_id](bool result) { - LLMarketplaceData::instance().activateListing(version_folder_id,false); + if (!result) + { + LLMarketplaceData::instance().activateListing(version_folder_id, false); + } } + ); } // In all cases, update the listing we moved from so suffix are updated update_marketplace_category(from_folder_uuid); @@ -3371,18 +3376,26 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) if (depth_nesting_in_marketplace(mUUID) == 1) { LLUUID version_folder_id = LLMarketplaceData::instance().getVersionFolder(mUUID); - LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id); mMessage = ""; - if (!validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3))) - { - LLSD subs; - subs["[ERROR_CODE]"] = mMessage; - LLNotificationsUtil::add("MerchantListingFailed", subs); - } - else + + LLMarketplaceValidator::getInstance()->validateMarketplaceListings( + version_folder_id, + [this, version_folder_id](bool result) { - LLMarketplaceData::instance().activateListing(mUUID,true); - } + // todo: might need to ensure bridge/mUUID exists or this will cause crashes + if (!result) + { + LLSD subs; + subs["[ERROR_CODE]"] = mMessage; + LLNotificationsUtil::add("MerchantListingFailed", subs); + } + else + { + LLMarketplaceData::instance().activateListing(mUUID, true); + } + }, + boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3) + ); } return; } @@ -3390,18 +3403,27 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) { if (depth_nesting_in_marketplace(mUUID) == 2) { - LLInventoryCategory* category = gInventory.getCategory(mUUID); mMessage = ""; - if (!validate_marketplacelistings(category,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),false,2)) - { - LLSD subs; - subs["[ERROR_CODE]"] = mMessage; - LLNotificationsUtil::add("MerchantFolderActivationFailed", subs); - } - else + + LLMarketplaceValidator::getInstance()->validateMarketplaceListings( + mUUID, + [this](bool result) { - LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), mUUID); - } + if (!result) + { + LLSD subs; + subs["[ERROR_CODE]"] = mMessage; + LLNotificationsUtil::add("MerchantFolderActivationFailed", subs); + } + else + { + LLInventoryCategory* category = gInventory.getCategory(mUUID); + LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), mUUID); + } + }, + boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3), + false, + 2); } return; } @@ -3424,29 +3446,44 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action) } else if ("marketplace_create_listing" == action) { - LLViewerInventoryCategory* cat = gInventory.getCategory(mUUID); mMessage = ""; - bool validates = validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),false); - if (!validates) + + // first run vithout fix_hierarchy, second run with fix_hierarchy + LLMarketplaceValidator::getInstance()->validateMarketplaceListings( + mUUID, + [this](bool result) { - mMessage = ""; - validates = validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),true); - if (validates) + if (!result) + { + mMessage = ""; + + LLMarketplaceValidator::getInstance()->validateMarketplaceListings( + mUUID, + [this](bool result) + { + if (result) + { + LLNotificationsUtil::add("MerchantForceValidateListing"); + LLMarketplaceData::instance().createListing(mUUID); + } + else + { + LLSD subs; + subs["[ERROR_CODE]"] = mMessage; + LLNotificationsUtil::add("MerchantListingFailed", subs); + } + }, + boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3), + true); + } + else { - LLNotificationsUtil::add("MerchantForceValidateListing"); + LLMarketplaceData::instance().createListing(mUUID); } - } + }, + boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3), + false); - if (!validates) - { - LLSD subs; - subs["[ERROR_CODE]"] = mMessage; - LLNotificationsUtil::add("MerchantListingFailed", subs); - } - else - { - LLMarketplaceData::instance().createListing(mUUID); - } return; } else if ("marketplace_disassociate_listing" == action) @@ -5296,11 +5333,15 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid); if (version_folder_id.notNull()) { - LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id); - if (!validate_marketplacelistings(cat,NULL)) + LLMarketplaceValidator::getInstance()->validateMarketplaceListings( + version_folder_id, + [version_folder_id](bool result) { - LLMarketplaceData::instance().activateListing(version_folder_id,false); - } + if (!result) + { + LLMarketplaceData::instance().activateListing(version_folder_id, false); + } + }); } } diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 6b406c4c9c..5975cb982b 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1492,7 +1492,7 @@ bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUU // Reparent the folder gInventory.changeCategoryParent(viewer_inv_cat, dest_folder, false); // Check the destination folder recursively for no copy items and promote the including folders if any - validate_marketplacelistings(dest_cat); + LLMarketplaceValidator::getInstance()->validateMarketplaceListings(dest_folder); } // Update the modified folders @@ -1517,32 +1517,23 @@ bool sort_alpha(const LLViewerInventoryCategory* cat1, const LLViewerInventoryCa return cat1->getName().compare(cat2->getName()) < 0; } -void dump_trace(std::string& message, S32 depth, LLError::ELevel log_level) -{ - LL_INFOS() << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message << LL_ENDL; -} - // Make all relevant business logic checks on the marketplace listings starting with the folder as argument. // This function does no deletion of listings but a mere audit and raises issues to the user (through the -// optional callback cb). It also returns a boolean, true if things validate, false if issues are raised. +// optional callback cb). // The only inventory changes that are done is to move and sort folders containing no-copy items to stock folders. -bool validate_marketplacelistings( +// @pending_callbacks - how many callbacks we are waiting for, must be inited before use +// @result - true if things validate, false if issues are raised, must be inited before use +typedef boost::function validation_result_callback_t; +void validate_marketplacelistings( LLInventoryCategory* cat, - validation_callback_t cb, + validation_result_callback_t cb_result, + LLMarketplaceValidator::validation_msg_callback_t cb_msg, bool fix_hierarchy, S32 depth, - bool notify_observers) + bool notify_observers, + S32 &pending_callbacks, + bool &result) { -#if 0 - // Used only for debug - if (!cb) - { - cb = boost::bind(&dump_trace, _1, _2, _3); - } -#endif - // Folder is valid unless issue is raised - bool result = true; - // Get the type and the depth of the folder LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (cat); const LLFolderType::EType folder_type = cat->getPreferredType(); @@ -1574,10 +1565,10 @@ bool validate_marketplacelistings( if (!can_move_folder_to_marketplace(cat, cat, cat, message, 0, fix_hierarchy)) { result = false; - if (cb) + if (cb_msg) { message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error") + " " + message; - cb(message,depth,LLError::LEVEL_ERROR); + cb_msg(message,depth,LLError::LEVEL_ERROR); } } } @@ -1587,26 +1578,42 @@ bool validate_marketplacelistings( { if (fix_hierarchy) { - if (cb) + if (cb_msg) { std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Warning") + " " + LLTrans::getString("Marketplace Validation Warning Stock"); - cb(message,depth,LLError::LEVEL_WARN); + cb_msg(message,depth,LLError::LEVEL_WARN); } + // Nest the stock folder one level deeper in a normal folder and restart from there + pending_callbacks++; LLUUID parent_uuid = cat->getParentUUID(); - LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, LLFolderType::FT_NONE, cat->getName()); - LLInventoryCategory* new_cat = gInventory.getCategory(folder_uuid); - gInventory.changeCategoryParent(viewer_cat, folder_uuid, false); - result &= validate_marketplacelistings(new_cat, cb, fix_hierarchy, depth + 1, notify_observers); - return result; + LLUUID cat_uuid = cat->getUUID(); + 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) + { + 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); + cb_result(pending, result); + } + ); + result = false; + return; } else { result = false; - if (cb) + if (cb_msg) { std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error") + " " + LLTrans::getString("Marketplace Validation Warning Stock"); - cb(message,depth,LLError::LEVEL_ERROR); + cb_msg(message,depth,LLError::LEVEL_ERROR); } } } @@ -1637,10 +1644,10 @@ bool validate_marketplacelistings( if (!can_move_to_marketplace(item, error_msg, false)) { has_bad_items = true; - if (cb && fix_hierarchy) + if (cb_msg && fix_hierarchy) { std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error") + " " + error_msg; - cb(message,depth,LLError::LEVEL_ERROR); + cb_msg(message,depth,LLError::LEVEL_ERROR); } continue; } @@ -1671,35 +1678,35 @@ bool validate_marketplacelistings( if (depth == 2) { // If this is an empty version folder, warn only (listing won't be delivered by AIS, but only AIS should unlist) - if (cb) + if (cb_msg) { std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Empty Version"); - cb(message,depth,LLError::LEVEL_WARN); + cb_msg(message,depth,LLError::LEVEL_WARN); } } else if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2)) { // If this is a legit but empty stock folder, warn only (listing must stay searchable when out of stock) - if (cb) + if (cb_msg) { std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Empty Stock"); - cb(message,depth,LLError::LEVEL_WARN); + cb_msg(message,depth,LLError::LEVEL_WARN); } } - else if (cb) + else if (cb_msg) { // We warn if there's nothing in a regular folder (may be it's an under construction listing) std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Warning Empty"); - cb(message,depth,LLError::LEVEL_WARN); + cb_msg(message,depth,LLError::LEVEL_WARN); } } else { // Done with that folder : Print out the folder name unless we already found an error here - if (cb && result && (depth >= 1)) + if (cb_msg && result && (depth >= 1)) { std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log"); - cb(message,depth,LLError::LEVEL_INFO); + cb_msg(message,depth,LLError::LEVEL_INFO); } } } @@ -1707,10 +1714,10 @@ bool validate_marketplacelistings( else if ((count == 1) && !has_bad_items && (((unique_key == default_key) && (depth > 1)) || ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2) && (cat_array->size() == 0)))) { // Done with that folder : Print out the folder name unless we already found an error here - if (cb && result && (depth >= 1)) + if (cb_msg && result && (depth >= 1)) { std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log"); - cb(message,depth,LLError::LEVEL_INFO); + cb_msg(message,depth,LLError::LEVEL_INFO); } } else @@ -1732,11 +1739,11 @@ bool validate_marketplacelistings( while (items_vector_it != items_vector.end()) { // Create a new folder - LLUUID parent_uuid = (depth > 2 ? viewer_cat->getParentUUID() : viewer_cat->getUUID()); + const LLUUID parent_uuid = (depth > 2 ? viewer_cat->getParentUUID() : viewer_cat->getUUID()); LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(items_vector_it->second.back()); std::string folder_name = (depth >= 1 ? viewer_cat->getName() : viewer_inv_item->getName()); LLFolderType::EType new_folder_type = (items_vector_it->first == default_key ? LLFolderType::FT_NONE : LLFolderType::FT_MARKETPLACE_STOCK); - if (cb) + if (cb_msg) { std::string message = ""; if (new_folder_type == LLFolderType::FT_MARKETPLACE_STOCK) @@ -1747,24 +1754,31 @@ bool validate_marketplacelistings( { message = indent + folder_name + LLTrans::getString("Marketplace Validation Warning Create Version"); } - cb(message,depth,LLError::LEVEL_WARN); + cb_msg(message,depth,LLError::LEVEL_WARN); } - std::vector &uuid_vector = items_vector_it->second; + + pending_callbacks++; + std::vector uuid_vector = items_vector_it->second; // needs to be a copy for lambda gInventory.createNewCategory( parent_uuid, new_folder_type, folder_name, - [uuid_vector, cb, indent, depth, parent_uuid, notify_observers](const LLUUID &new_category_id) + [uuid_vector, cb_result, cb_msg, depth, parent_uuid, notify_observers](const LLUUID &new_category_id) { // Move each item to the new folder - std::vector::reverse_iterator iter = uuid_vector.rbegin(); + std::vector::const_reverse_iterator iter = uuid_vector.rbegin(); while (iter != uuid_vector.rend()) { LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(*iter); - if (cb) + if (cb_msg) { + std::string indent; + for (int i = 1; i < depth; i++) + { + indent += " "; + } std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Move"); - cb(message, depth, LLError::LEVEL_WARN); + cb_msg(message, depth, LLError::LEVEL_WARN); } gInventory.changeItemParent(viewer_inv_item, new_category_id, true); iter++; @@ -1777,6 +1791,7 @@ bool validate_marketplacelistings( { gInventory.notifyObservers(); } + cb_result(0, true); } ); items_vector_it++; @@ -1792,11 +1807,11 @@ bool validate_marketplacelistings( { LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (*iter); gInventory.changeCategoryParent(viewer_cat, parent_uuid, false); - result &= validate_marketplacelistings(viewer_cat, cb, fix_hierarchy, depth, false); + validate_marketplacelistings(viewer_cat, cb_result, cb_msg, fix_hierarchy, depth, false, pending_callbacks, result); } } } - else if (cb) + else if (cb_msg) { // We are not fixing the hierarchy but reporting problems, report everything we can find // Print the folder name @@ -1807,20 +1822,20 @@ bool validate_marketplacelistings( // Report if a stock folder contains a mix of items result = false; std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Mixed Stock"); - cb(message,depth,LLError::LEVEL_ERROR); + cb_msg(message,depth,LLError::LEVEL_ERROR); } else if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (cat_array->size() != 0)) { // Report if a stock folder contains subfolders result = false; std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Subfolder In Stock"); - cb(message,depth,LLError::LEVEL_ERROR); + cb_msg(message,depth,LLError::LEVEL_ERROR); } else { // Simply print the folder name std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log"); - cb(message,depth,LLError::LEVEL_INFO); + cb_msg(message,depth,LLError::LEVEL_INFO); } } // Scan each item and report if there's a problem @@ -1835,21 +1850,21 @@ bool validate_marketplacelistings( // Report items that shouldn't be there to start with result = false; std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error") + " " + error_msg; - cb(message,depth,LLError::LEVEL_ERROR); + cb_msg(message,depth,LLError::LEVEL_ERROR); } else if ((!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) && (folder_type != LLFolderType::FT_MARKETPLACE_STOCK)) { // Report stock items that are misplaced result = false; std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error Stock Item"); - cb(message,depth,LLError::LEVEL_ERROR); + cb_msg(message,depth,LLError::LEVEL_ERROR); } else if (depth == 1) { // Report items not wrapped in version folder result = false; std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Unwrapped Item"); - cb(message,depth,LLError::LEVEL_ERROR); + cb_msg(message,depth,LLError::LEVEL_ERROR); } } } @@ -1858,17 +1873,18 @@ bool validate_marketplacelistings( if (viewer_cat->getDescendentCount() == 0) { // Remove the current folder if it ends up empty - if (cb) + if (cb_msg) { std::string message = indent + viewer_cat->getName() + LLTrans::getString("Marketplace Validation Warning Delete"); - cb(message,depth,LLError::LEVEL_WARN); + cb_msg(message,depth,LLError::LEVEL_WARN); } gInventory.removeCategory(cat->getUUID()); if (notify_observers) { gInventory.notifyObservers(); } - return result && !has_bad_items; + result &=!has_bad_items; + return; } } @@ -1881,15 +1897,15 @@ bool validate_marketplacelistings( for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++) { LLInventoryCategory* category = *iter; - result &= validate_marketplacelistings(category, cb, fix_hierarchy, depth + 1, false); + validate_marketplacelistings(category, cb_result, cb_msg, fix_hierarchy, depth + 1, false, pending_callbacks, result); } - + update_marketplace_category(cat->getUUID(), true, true); if (notify_observers) { gInventory.notifyObservers(); } - return result && !has_bad_items; + result &= !has_bad_items; } void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id) @@ -1989,8 +2005,91 @@ void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::st inventory_func_type func = boost::bind(&move_items_to_folder, _1, selected_uuids); gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func); +} + +///---------------------------------------------------------------------------- +/// LLMarketplaceValidator implementations +///---------------------------------------------------------------------------- + +LLMarketplaceValidator::LLMarketplaceValidator() +{ } +LLMarketplaceValidator::~LLMarketplaceValidator() +{ +} + +void LLMarketplaceValidator::validateMarketplaceListings( + const LLUUID &category_id, + LLMarketplaceValidator::validation_done_callback_t cb_done, + LLMarketplaceValidator::validation_msg_callback_t cb_msg, + bool fix_hierarchy, + S32 depth) +{ + + mValidationQueue.emplace(category_id, cb_done, cb_msg, fix_hierarchy, depth); + if (!mValidationInProgress) + { + start(); + } +} + +void LLMarketplaceValidator::start() +{ + if (mValidationQueue.empty()) + { + mValidationInProgress = false; + return; + } + mValidationInProgress = true; + mPendingCallbacks = 1; // do '1' in case something decides ro callback immediately + const ValidationRequest &first = mValidationQueue.front(); + LLViewerInventoryCategory* cat = gInventory.getCategory(first.mCategoryId); + + validation_result_callback_t result_callback = [](S32 pending, bool result) + { + LLMarketplaceValidator* validator = LLMarketplaceValidator::getInstance(); + validator->mPendingCallbacks--; // we just got a callback + validator->mPendingCallbacks += pending; + validator->mPendingResult &= result; + if (validator->mPendingCallbacks <= 0) + { + llassert(validator->mPendingCallbacks == 0); // shouldn't be below 0 + const ValidationRequest &first = validator->mValidationQueue.front(); + if (first.mCbDone) + { + first.mCbDone(validator->mPendingResult); + } + validator->mValidationQueue.pop(); // done; + validator->start(); + } + }; + + validate_marketplacelistings( + cat, + result_callback, + first.mCbMsg, + first.mFixHierarchy, + first.mDepth, + true, + mPendingCallbacks, + mPendingResult); + + result_callback(mPendingCallbacks, mPendingResult); +} + +LLMarketplaceValidator::ValidationRequest::ValidationRequest( + LLUUID category_id, + validation_done_callback_t cb_done, + validation_msg_callback_t cb_msg, + bool fix_hierarchy, + S32 depth) +: mCategoryId(category_id) +, mCbDone(cb_done) +, mCbMsg(cb_msg) +, mFixHierarchy(fix_hierarchy) +, mDepth(depth) +{} ///---------------------------------------------------------------------------- /// LLInventoryCollectFunctor implementations diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index 56ad6f6496..ec5e53f9a6 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -81,13 +81,12 @@ void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryMode // Generates a string containing the path to the item specified by item_id. void append_path(const LLUUID& id, std::string& path); -typedef boost::function validation_callback_t; bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false); bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size = 1, bool check_items = true, bool from_paste = false); bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy = false); bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy = false, bool move_no_copy_items = false); -bool validate_marketplacelistings(LLInventoryCategory* inv_cat, validation_callback_t cb = NULL, bool fix_hierarchy = true, S32 depth = -1, bool notify_observers = true); + S32 depth_nesting_in_marketplace(LLUUID cur_uuid); LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth); S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false); @@ -102,6 +101,50 @@ bool is_only_items_selected(const uuid_vec_t& selected_uuids); ** ** *******************************************************************************/ +class LLMarketplaceValidator: public LLSingleton +{ + LLSINGLETON(LLMarketplaceValidator); + ~LLMarketplaceValidator(); + LOG_CLASS(LLMarketplaceValidator); +public: + + typedef boost::function validation_msg_callback_t; + typedef boost::function validation_done_callback_t; + + void validateMarketplaceListings( + const LLUUID &category_id, + validation_done_callback_t cb_done = NULL, + validation_msg_callback_t cb_msg = NULL, + bool fix_hierarchy = true, + S32 depth = -1); + +private: + void start(); + + class ValidationRequest + { + public: + ValidationRequest( + LLUUID category_id, + validation_done_callback_t cb_done, + validation_msg_callback_t cb_msg, + bool fix_hierarchy, + S32 depth); + LLUUID mCategoryId; + validation_done_callback_t mCbDone; + validation_msg_callback_t mCbMsg; + bool mFixHierarchy; + S32 mDepth; + }; + + bool mValidationInProgress; + S32 mPendingCallbacks; + bool mPendingResult; + // todo: might be a good idea to memorize requests by id and + // filter out ones that got multiple validation requests + std::queue mValidationQueue; +}; + /******************************************************************************** ** ** ** INVENTORY COLLECTOR FUNCTIONS diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index b2cfc8584e..774ed051c0 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -954,27 +954,23 @@ const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::ETyp // Convenience function to create a new category. You could call // updateCategory() with a newly generated UUID category, but this // version will take care of details like what the name should be -// based on preferred type. Returns the UUID of the new category. -// -// On failure, returns a null UUID. -// FIXME: callers do not check for or handle a null results currently. -LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, +// based on preferred type. +void LLInventoryModel::createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, const std::string& pname, inventory_func_type callback) { - LLUUID id; // Initially null. if (!isInventoryUsable()) { LL_WARNS(LOG_INV) << "Inventory is not usable; can't create requested category of type " << preferred_type << LL_ENDL; - return id; + return; } if(LLFolderType::lookup(preferred_type) == LLFolderType::badLookup()) { LL_DEBUGS(LOG_INV) << "Attempt to create undefined category." << LL_ENDL; - return id; + return; } if (preferred_type != LLFolderType::FT_NONE) @@ -990,24 +986,53 @@ 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 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 && AISAPI::isAvailable()) { - // 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()); LLSD cat_sd = cat.asLLSD(); new_inventory["categories"].append(cat_sd); - AISAPI::CreateInventory(parent_id, new_inventory, callback); + AISAPI::CreateInventory( + parent_id, + new_inventory, + [this, callback, parent_id, preferred_type, name] (const LLUUID& new_category) + { + if (new_category.isNull()) + { + callback(new_category); + return; + } + + LLViewerInventoryCategory* folderp = gInventory.getCategory(new_category); + if (!folderp) + { + // Add the category to the internal representation + LLPointer cat = new LLViewerInventoryCategory( + new_category, + parent_id, + preferred_type, + name, + gAgent.getID()); + + LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); + accountForUpdate(update); + + cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 + cat->setDescendentCount(0); + updateCategory(cat); + } - return LLUUID::null; + callback(new_category); + }); + return; } -#else +#endif LLViewerRegion* viewer_region = gAgent.getRegion(); std::string url; if ( viewer_region ) @@ -1016,7 +1041,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, if (!url.empty() && callback) { //Let's use the new capability. - + LLUUID id; id.generate(); LLSD request, body; body["folder_id"] = id; @@ -1030,48 +1055,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, 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; - } - - // 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()); - cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1 - cat->setDescendentCount(0); - LLCategoryUpdate update(cat->getParentUUID(), 1); - accountForUpdate(update); - updateCategory(cat); - - LL_DEBUGS(LOG_INV) << "Creating category via UDP message CreateInventoryFolder, type " << preferred_type << LL_ENDL; - - // Create the category on the server. We do this to prevent people - // from munging their protected folders. - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("CreateInventoryFolder"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlock("FolderData"); - cat->packMessage(msg); - gAgent.sendReliableMessage(); - - // return the folder id of the newly created folder - return id; } void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inventory_func_type callback) @@ -1095,12 +1079,20 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv if (!status) { LL_WARNS() << "HTTP failure attempting to create category." << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } return; } if (!result.has("folder_id")) { LL_WARNS() << "Malformed response contents" << ll_pretty_print_sd(result) << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } return; } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 1fde5a3b2f..5f8db30390 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -477,7 +477,7 @@ public: public: // Returns the UUID of the new category. If you want to use the default // name based on type, pass in a NULL to the 'name' parameter. - LLUUID createNewCategory(const LLUUID& parent_id, + void createNewCategory(const LLUUID& parent_id, LLFolderType::EType preferred_type, const std::string& name, inventory_func_type callback = NULL); diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 5b86f2cc4b..4038afc74c 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -700,10 +700,9 @@ void LLMarketplaceInventoryObserver::onIdleProcessQueue(void *userdata) // If it's a folder known to the marketplace, let's check it's in proper shape if (LLMarketplaceData::instance().isListed(*id_it) || LLMarketplaceData::instance().isVersionFolder(*id_it)) { - LLInventoryCategory* cat = (LLInventoryCategory*)(obj); // can trigger notifyObservers // can cause more structural changes - validate_marketplacelistings(cat); + LLMarketplaceValidator::getInstance()->validateMarketplaceListings(obj->getUUID()); } } else @@ -1848,8 +1847,7 @@ void LLMarketplaceData::decrementValidationWaiting(const LLUUID& folder_id, S32 if (found->second <= 0) { mValidationWaitingList.erase(found); - LLInventoryCategory *cat = gInventory.getCategory(folder_id); - validate_marketplacelistings(cat); + LLMarketplaceValidator::getInstance()->validateMarketplaceListings(folder_id); update_marketplace_category(folder_id); gInventory.notifyObservers(); } -- cgit v1.3 From 0d1f7cafcd9db3ffff8e22f898005dc34bca5fcb Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 11 Mar 2023 13:49:28 +0200 Subject: SL-19109 Fix item updates not getting a callback --- indra/newview/llaisapi.cpp | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 3826da0341..8e20132ede 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -483,20 +483,17 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht gInventory.onAISUpdateReceived("AISCommand", result); if (callback && !callback.empty()) - { + { + bool needs_callback = true; LLUUID id(LLUUID::null); - if (type == COPYLIBRARYCATEGORY) - { - if (result.has("category_id")) - { - id = result["category_id"]; - } //else signal failure - callback(id); + if (type == COPYLIBRARYCATEGORY && result.has("category_id")) + { + id = result["category_id"]; } if (type == CREATEINVENTORY) { - bool informed_caller = false; + // CREATEINVENTORY can have multiple callbacks if (result.has("_created_categories")) { LLSD& cats = result["_created_categories"]; @@ -505,7 +502,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht { LLUUID cat_id = *cat_iter; callback(cat_id); - informed_caller = true; + needs_callback = false; } } if (result.has("_created_items")) @@ -516,17 +513,17 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht { LLUUID item_id = *item_iter; callback(item_id); - informed_caller = true; + needs_callback = false; } } - - if (!informed_caller) - { - // signal failure with null id - callback(id); - } } + if (needs_callback) + { + // Call callback at least once regardless of failure. + // UPDATEITEM doesn't expect an id + callback(id); + } } } -- cgit v1.3 From f14629e690c31b4fb9381430e288f191ef22d23a Mon Sep 17 00:00:00 2001 From: Mnikolenko Productengine Date: Fri, 3 Mar 2023 12:15:09 +0200 Subject: SL-18629 AISv3 draft calls --- indra/newview/llaisapi.cpp | 181 ++++++++++++++++++++++++++++++++++++++++++++- indra/newview/llaisapi.h | 15 +++- 2 files changed, 194 insertions(+), 2 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 8e20132ede..afc307278c 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -368,6 +368,153 @@ void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t EnqueueAISCommand("UpdateItem", proc); } +/*static*/ +void AISAPI::FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callback) +{ + + std::string cap; + + cap = (type == INVENTORY) ? getInvCap() : getLibCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + std::string url = cap + std::string("/item/") + itemId.asString(); + + invokationFn_t patchFn = 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, patchFn, url, itemId, LLSD(), callback, FETCHITEM)); + + EnqueueAISCommand("FetchItem", proc); +} + +/*static*/ +void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool recursive, completion_t callback, S32 depth) +{ + std::string cap; + + cap = (type == INVENTORY) ? getInvCap() : getLibCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + std::string url = cap + std::string("/category/") + catId.asString() + "/children"; + + if (recursive) + { + url += "?depth=*"; + } + else + { + url += "?depth=" + std::to_string(depth); + } + + invokationFn_t patchFn = 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, patchFn, url, catId, LLSD(), callback, FETCHCATEGORYCHILDREN)); + + EnqueueAISCommand("FetchCategoryChildren", proc); +} + +/*static*/ +void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool recursive, completion_t callback, S32 depth) +{ + std::string cap; + + cap = (type == INVENTORY) ? getInvCap() : getLibCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + std::string url = cap + std::string("/category/") + catId.asString() + "/categories"; + + if (recursive) + { + url += "?depth=*"; + } + else + { + url += "?depth=" + std::to_string(depth); + } + + invokationFn_t patchFn = 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, patchFn, url, catId, LLSD(), callback, FETCHCATEGORYCATEGORIES)); + + EnqueueAISCommand("FetchCategoryCategories", proc); +} + +/*static*/ +void AISAPI::FetchCOF(completion_t callback) +{ + std::string cap; + cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + + std::string url = cap + std::string("/category/") + cof_id.asString() + "/links"; + + //LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ROOT_INVENTORY); + //std::string url = cap + std::string("/category/") + root_id.asString() + "/children?depth=*"; + + invokationFn_t patchFn = 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, patchFn, url, cof_id, LLSD(), callback, FETCHCOF)); + + EnqueueAISCommand("FetchCOF", proc); +} + /*static*/ void AISAPI::EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc) { @@ -427,7 +574,12 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); LLCore::HttpHeaders::ptr_t httpHeaders; - httpOptions->setTimeout(LLCoreHttpUtil::HTTP_REQUEST_EXPIRY_SECS); + /*if (type == FETCHCATEGORYCHILDREN && (url.find("?depth=*") != std::string::npos)) + { + LL_WARNS() << "testy test start"<< LL_ENDL; + }*/ + + httpOptions->setTimeout(180); LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; @@ -475,9 +627,36 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } } } + /*else if (status.getType() == 403) + { + if (type == FETCHCATEGORYCHILDREN) + { + if (url.find("?depth=*") != std::string::npos) + { + LL_WARNS() << "too much" << LL_ENDL; + AISAPI::FetchCategoryChildren(gInventory.getRootFolderID(), AISAPI::ITEM_TYPE::INVENTORY, false, boost::bind(&LLInventoryModel::fetchDescendentsDepthOne, &gInventory, targetId)); + + if (result["oversize_inventory"].asBoolean() == true) + { + LL_WARNS("Inventory") << "Can't fetch the oversized inventory folder" << LL_ENDL; + } + } + else + { + if (result["oversize_inventory"].asBoolean() == true) + { + LL_WARNS("Inventory") << "Can't fetch the oversized inventory folder" << LL_ENDL; + } + } + } + }*/ LL_WARNS("Inventory") << "Inventory error: " << status.toString() << LL_ENDL; LL_WARNS("Inventory") << ll_pretty_print_sd(result) << LL_ENDL; } + else if (type == FETCHCOF) + { + //LL_WARNS("Inventory") << ll_pretty_print_sd(result) << LL_ENDL; + } LL_DEBUGS("Inventory") << result << LL_ENDL; gInventory.onAISUpdateReceived("AISCommand", result); diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 6e9cc19baa..b21edb9f33 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -38,6 +38,11 @@ class AISAPI { public: + typedef enum { + INVENTORY, + LIBRARY + } ITEM_TYPE; + typedef boost::function completion_t; static bool isAvailable(); @@ -50,6 +55,10 @@ public: static void PurgeDescendents(const LLUUID &categoryId, completion_t callback = completion_t()); static void UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback = completion_t()); static void UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback = completion_t()); + static void FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callback = completion_t()); + 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 FetchCategoryCategories(const LLUUID &catId, 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 CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t()); private: @@ -62,7 +71,11 @@ private: UPDATECATEGORY, UPDATEITEM, COPYLIBRARYCATEGORY, - CREATEINVENTORY + CREATEINVENTORY, + FETCHITEM, + FETCHCATEGORYCHILDREN, + FETCHCATEGORYCATEGORIES, + FETCHCOF, } COMMAND_TYPE; static const std::string INVENTORY_CAP_NAME; -- cgit v1.3 From ac145cb21f382b8eab9f770cecfa23ea9d58aac6 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 14 Mar 2023 23:21:26 +0200 Subject: SL-18629 WIP Fetch Inventory using AIS caps --- indra/newview/llaisapi.cpp | 42 ++++- indra/newview/llaisapi.h | 4 +- indra/newview/llinventoryfilter.cpp | 2 +- indra/newview/llinventorymodel.cpp | 13 -- indra/newview/llinventorymodel.h | 3 - indra/newview/llinventorymodelbackgroundfetch.cpp | 214 ++++++++++++++++++---- indra/newview/llinventorymodelbackgroundfetch.h | 47 ++--- indra/newview/llstartup.cpp | 1 + indra/newview/llviewerinventory.cpp | 2 +- 9 files changed, 242 insertions(+), 86 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index afc307278c..87811e9c0b 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -33,6 +33,8 @@ #include "llinventorymodel.h" #include "llsdutil.h" #include "llviewerregion.h" +#include "llvoavatar.h" +#include "llvoavatarself.h" #include "llinventoryobserver.h" #include "llviewercontrol.h" @@ -409,6 +411,7 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + callback(LLUUID::null); return; } std::string url = cap + std::string("/category/") + catId.asString() + "/children"; @@ -565,6 +568,24 @@ void AISAPI::onIdle(void *userdata) } } +/*static*/ +void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type) +{ + LLTimer timer; + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + { + dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); + } + bool is_fetch = (type == FETCHITEM) + || (type == FETCHCATEGORYCHILDREN) + || (type == FETCHCATEGORYCATEGORIES) + || (type == FETCHCOF); + // parse update llsd into stuff to do or parse received items. + AISUpdate ais_update(update, is_fetch); + ais_update.doUpdate(); // execute the updates in the appropriate order. + LL_INFOS("Inventory") << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; +} + /*static*/ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter, invokationFn_t invoke, std::string url, @@ -659,7 +680,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } LL_DEBUGS("Inventory") << result << LL_ENDL; - gInventory.onAISUpdateReceived("AISCommand", result); + onUpdateReceived("AISCommand", result, type); if (callback && !callback.empty()) { @@ -708,7 +729,8 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } //------------------------------------------------------------------------- -AISUpdate::AISUpdate(const LLSD& update) +AISUpdate::AISUpdate(const LLSD& update, bool fetch) +: mFetch(fetch) { parseUpdate(update); } @@ -849,7 +871,7 @@ void AISUpdate::parseItem(const LLSD& item_map) BOOL rv = new_item->unpackMessage(item_map); if (rv) { - if (curr_item) + if (!mFetch && curr_item) { mItemsUpdated[item_id] = new_item; // This statement is here to cause a new entry with 0 @@ -884,7 +906,7 @@ void AISUpdate::parseLink(const LLSD& link_map) if (rv) { const LLUUID& parent_id = new_link->getParentUUID(); - if (curr_link) + if (!mFetch && curr_link) { mItemsUpdated[item_id] = new_link; // This statement is here to cause a new entry with 0 @@ -951,7 +973,7 @@ void AISUpdate::parseCategory(const LLSD& category_map) //} if (rv) { - if (curr_cat) + if (curr_cat && !mFetch) { mCategoriesUpdated[category_id] = new_cat; // This statement is here to cause a new entry with 0 @@ -1054,7 +1076,7 @@ void AISUpdate::parseEmbeddedLinks(const LLSD& links) { const LLUUID link_id((*linkit).first); const LLSD& link_map = (*linkit).second; - if (mItemIds.end() == mItemIds.find(link_id)) + if (!mFetch && mItemIds.end() == mItemIds.find(link_id)) { LL_DEBUGS("Inventory") << "Ignoring link not in items list " << link_id << LL_ENDL; } @@ -1070,7 +1092,7 @@ void AISUpdate::parseEmbeddedItem(const LLSD& item) // a single item (_embedded in a link) if (item.has("item_id")) { - if (mItemIds.end() != mItemIds.find(item["item_id"].asUUID())) + if (mFetch || mItemIds.end() != mItemIds.find(item["item_id"].asUUID())) { parseItem(item); } @@ -1086,7 +1108,7 @@ void AISUpdate::parseEmbeddedItems(const LLSD& items) { const LLUUID item_id((*itemit).first); const LLSD& item_map = (*itemit).second; - if (mItemIds.end() == mItemIds.find(item_id)) + if (!mFetch && mItemIds.end() == mItemIds.find(item_id)) { LL_DEBUGS("Inventory") << "Ignoring item not in items list " << item_id << LL_ENDL; } @@ -1102,7 +1124,7 @@ void AISUpdate::parseEmbeddedCategory(const LLSD& category) // a single category (_embedded in a link) if (category.has("category_id")) { - if (mCategoryIds.end() != mCategoryIds.find(category["category_id"].asUUID())) + if (mFetch || mCategoryIds.end() != mCategoryIds.find(category["category_id"].asUUID())) { parseCategory(category); } @@ -1118,7 +1140,7 @@ void AISUpdate::parseEmbeddedCategories(const LLSD& categories) { const LLUUID category_id((*categoryit).first); const LLSD& category_map = (*categoryit).second; - if (mCategoryIds.end() == mCategoryIds.find(category_id)) + if (!mFetch && mCategoryIds.end() == mCategoryIds.find(category_id)) { LL_DEBUGS("Inventory") << "Ignoring category not in categories list " << category_id << LL_ENDL; } diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index b21edb9f33..3de3366a0e 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -86,6 +86,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); static std::string getInvCap(); static std::string getLibCap(); @@ -101,7 +102,7 @@ private: class AISUpdate { public: - AISUpdate(const LLSD& update); + AISUpdate(const LLSD& update, bool fetch); void parseUpdate(const LLSD& update); void parseMeta(const LLSD& update); void parseContent(const LLSD& update); @@ -137,6 +138,7 @@ private: uuid_list_t mObjectsDeletedIds; uuid_list_t mItemIds; uuid_list_t mCategoryIds; + bool mFetch; }; #endif diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index d6110b3cd5..6e09161473 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -202,7 +202,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const { // At the moment background fetch only cares about VERSION_UNKNOWN, // so do not check isCategoryComplete that compares descendant count - LLInventoryModelBackgroundFetch::instance().start(folder_id); + LLInventoryModelBackgroundFetch::instance().start(folder_id, false); } } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index ee0dd2422a..65690228e7 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1754,19 +1754,6 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, notifyObservers(); } -void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update) -{ - LLTimer timer; - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) - { - dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); - } - - AISUpdate ais_update(update); // parse update llsd into stuff to do. - ais_update.doUpdate(); // execute the updates in the appropriate order. - LL_INFOS(LOG_INV) << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; -} - // Does not appear to be used currently. void LLInventoryModel::onItemUpdated(const LLUUID& item_id, const LLSD& updates, bool update_parent_version) { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 3fbf8924b5..5e4319bb12 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -411,9 +411,6 @@ public: // Delete //-------------------------------------------------------------------- public: - - // Update model after an AISv3 update received for any operation. - void onAISUpdateReceived(const std::string& context, const LLSD& update); // Update model after an item is confirmed as removed from // server. Works for categories or items. diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 406c8b89d0..1905a9c9a4 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llinventorymodelbackgroundfetch.h" +#include "llaisapi.h" #include "llagent.h" #include "llappviewer.h" #include "llcallbacklist.h" @@ -184,12 +185,12 @@ const char * const LOG_INV("Inventory"); ///---------------------------------------------------------------------------- LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch(): - mBackgroundFetchActive(FALSE), + mBackgroundFetchActive(false), mFolderFetchActive(false), mFetchCount(0), - mAllFoldersFetched(FALSE), - mRecursiveInventoryFetchStarted(FALSE), - mRecursiveLibraryFetchStarted(FALSE), + mAllFoldersFetched(false), + mRecursiveInventoryFetchStarted(false), + mRecursiveLibraryFetchStarted(false), mMinTimeBetweenFetches(0.3f) {} @@ -241,17 +242,17 @@ BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const return mFolderFetchActive; } -void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, BOOL recursive, bool is_category) +void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, bool recursive, bool is_category) { mFetchQueue.push_front(FetchQueueInfo(id, recursive, is_category)); } -void LLInventoryModelBackgroundFetch::addRequestAtBack(const LLUUID & id, BOOL recursive, bool is_category) +void LLInventoryModelBackgroundFetch::addRequestAtBack(const LLUUID & id, bool recursive, bool is_category) { mFetchQueue.push_back(FetchQueueInfo(id, recursive, is_category)); } -void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) +void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) { LLViewerInventoryCategory * cat(gInventory.getCategory(id)); @@ -260,31 +261,57 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) // it's a folder, do a bulk fetch LL_DEBUGS(LOG_INV) << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL; - mBackgroundFetchActive = TRUE; + mBackgroundFetchActive = true; mFolderFetchActive = true; if (id.isNull()) { if (! mRecursiveInventoryFetchStarted) { mRecursiveInventoryFetchStarted |= recursive; - mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); + if (recursive && AISAPI::isAvailable()) + { + mRecursiveFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); + } + else + { + mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); + } gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } if (! mRecursiveLibraryFetchStarted) { mRecursiveLibraryFetchStarted |= recursive; - mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); + if (recursive && AISAPI::isAvailable()) + { + mRecursiveFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); + } + else + { + mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); + } gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } else { - // Specific folder requests go to front of queue. - if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id) - { - mFetchQueue.push_front(FetchQueueInfo(id, recursive)); - gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); - } + if (recursive && AISAPI::isAvailable()) + { + // AIS does depth requests, recursive requests will need to be prioritizes + if (mRecursiveFetchQueue.empty() || mRecursiveFetchQueue.back().mUUID != id) + { + mRecursiveFetchQueue.push_back(FetchQueueInfo(id, recursive)); + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + } + } + else + { + // Specific folder requests go to front of queue. + if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id) + { + mFetchQueue.push_front(FetchQueueInfo(id, recursive)); + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + } + } if (id == gInventory.getLibraryRootFolderID()) { mRecursiveLibraryFetchStarted |= recursive; @@ -299,7 +326,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) { if (! itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)) { - mBackgroundFetchActive = TRUE; + mBackgroundFetchActive = true; mFetchQueue.push_front(FetchQueueInfo(id, false, false)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); @@ -309,9 +336,9 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) void LLInventoryModelBackgroundFetch::findLostItems() { - mBackgroundFetchActive = TRUE; + mBackgroundFetchActive = true; mFolderFetchActive = true; - mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, TRUE)); + mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, true)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } @@ -320,7 +347,7 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched() if (mRecursiveInventoryFetchStarted && mRecursiveLibraryFetchStarted) { - mAllFoldersFetched = TRUE; + mAllFoldersFetched = true; //LL_INFOS(LOG_INV) << "All folders fetched, validating" << LL_ENDL; //gInventory.validate(); } @@ -338,8 +365,15 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() { if (mBackgroundFetchActive && gAgent.getRegion() && gAgent.getRegion()->capabilitiesReceived()) { - // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. - bulkFetch(); + if (AISAPI::isAvailable()) + { + bulkFetchViaAis(); + } + else + { + // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. + bulkFetch(); + } } } @@ -352,9 +386,118 @@ void LLInventoryModelBackgroundFetch::incrFetchCount(S32 fetching) mFetchCount = 0; } } +void ais_callback(const LLUUID& inv_id) +{ + LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); +} static LLTrace::BlockTimerStatHandle FTM_BULK_FETCH("Bulk Fetch"); +void LLInventoryModelBackgroundFetch::bulkFetchViaAis() +{ + LL_RECORD_BLOCK_TIME(FTM_BULK_FETCH); + //Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped. + if (gDisconnected) + { + return; + } + + static const S32 max_concurrent_fetches(12); + + if (mFetchCount >= max_concurrent_fetches) + { + return; + } + + // Start with recursive queue since it can get multiple categories + // in a single request and might contain what other requests want + while (!mRecursiveFetchQueue.empty() && mFetchCount < max_concurrent_fetches) + { + const FetchQueueInfo & fetch_info(mRecursiveFetchQueue.front()); + bulkFetchViaAis(fetch_info); + mRecursiveFetchQueue.pop_front(); + } + + while (!mFetchQueue.empty() && mFetchCount < max_concurrent_fetches) + { + const FetchQueueInfo & fetch_info(mFetchQueue.front()); + bulkFetchViaAis(fetch_info); + mFetchQueue.pop_front(); + } + + if (isBulkFetchProcessingComplete()) + { + setAllFoldersFetched(); + } +} + +void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetch_info) +{ + if (fetch_info.mIsCategory) + { + const LLUUID & cat_id(fetch_info.mUUID); + if (cat_id.isNull()) // Lost and found + { + AISAPI::FetchCategoryChildren(LLUUID::null, AISAPI::INVENTORY, false, ais_callback); + mFetchCount++; + } + else + { + const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); + + if (cat) + { + if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) + { + if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) + { + AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::LIBRARY, fetch_info.mRecursive, ais_callback); + } + else + { + AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::INVENTORY, fetch_info.mRecursive, ais_callback); + } + mFetchCount++; + } + else + { + // Already fetched, check if anything inside needs fetching + if (fetch_info.mRecursive) + { + LLInventoryModel::cat_array_t * categories(NULL); + LLInventoryModel::item_array_t * items(NULL); + gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); + for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); + it != categories->end(); + ++it) + { + mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); + } + } + } + } + // else??? + } + } + else + { + LLViewerInventoryItem * itemp(gInventory.getItem(fetch_info.mUUID)); + + if (itemp) + { + if (itemp->getPermissions().getOwner() == gAgent.getID()) + { + AISAPI::FetchItem(itemp->getUUID(), AISAPI::INVENTORY, ais_callback); + } + else + { + AISAPI::FetchItem(itemp->getUUID(), AISAPI::LIBRARY, ais_callback); + } + mFetchCount++; + } + } +} + // Bundle up a bunch of requests to send all at once. void LLInventoryModelBackgroundFetch::bulkFetch() { @@ -374,13 +517,6 @@ void LLInventoryModelBackgroundFetch::bulkFetch() // inventory more quickly. static const U32 max_batch_size(10); static const S32 max_concurrent_fetches(12); // Outstanding requests, not connections - static const F32 new_min_time(0.05f); // *HACK: Clean this up when old code goes away entirely. - - mMinTimeBetweenFetches = new_min_time; - if (mMinTimeBetweenFetches < new_min_time) - { - mMinTimeBetweenFetches = new_min_time; // *HACK: See above. - } if (mFetchCount) { @@ -394,8 +530,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() gInventory.notifyObservers(); } - if ((mFetchCount > max_concurrent_fetches) || - (mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches)) + if (mFetchCount > max_concurrent_fetches) { return; } @@ -414,6 +549,13 @@ void LLInventoryModelBackgroundFetch::bulkFetch() LLSD item_request_body; LLSD item_request_body_lib; + if (!mRecursiveFetchQueue.empty()) + { + LL_DEBUGS(LOG_INV) << "Request was sheduled for AIS, using legacy" << LL_ENDL; + mFetchQueue.insert(mFetchQueue.begin(), mRecursiveFetchQueue.begin(), mRecursiveFetchQueue.end()); + mRecursiveFetchQueue.clear(); + } + while (! mFetchQueue.empty() && (item_count + folder_count) < max_batch_size) { @@ -421,14 +563,14 @@ void LLInventoryModelBackgroundFetch::bulkFetch() if (fetch_info.mIsCategory) { const LLUUID & cat_id(fetch_info.mUUID); - if (cat_id.isNull()) //DEV-17797 + if (cat_id.isNull()) //DEV-17797 Lost and found { LLSD folder_sd; folder_sd["folder_id"] = LLUUID::null.asString(); folder_sd["owner_id"] = gAgent.getID(); folder_sd["sort_order"] = LLSD::Integer(sort_order); - folder_sd["fetch_folders"] = LLSD::Boolean(FALSE); - folder_sd["fetch_items"] = LLSD::Boolean(TRUE); + folder_sd["fetch_folders"] = LLSD::Boolean(false); + folder_sd["fetch_items"] = LLSD::Boolean(true); folder_request_body["folders"].append(folder_sd); folder_count++; } @@ -444,8 +586,8 @@ void LLInventoryModelBackgroundFetch::bulkFetch() folder_sd["folder_id"] = cat->getUUID(); folder_sd["owner_id"] = cat->getOwnerID(); folder_sd["sort_order"] = LLSD::Integer(sort_order); - folder_sd["fetch_folders"] = LLSD::Boolean(TRUE); //(LLSD::Boolean)sFullFetchStarted; - folder_sd["fetch_items"] = LLSD::Boolean(TRUE); + folder_sd["fetch_folders"] = LLSD::Boolean(true); //(LLSD::Boolean)sFullFetchStarted; + folder_sd["fetch_items"] = LLSD::Boolean(true); if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) { diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 00d2908c1b..ac1c42e0d7 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -49,7 +49,7 @@ public: // Start and stop background breadth-first fetching of inventory contents. // This gets triggered when performing a filter-search. - void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE); + void start(const LLUUID& cat_id = LLUUID::null, bool recursive = true); BOOL folderFetchActive() const; bool isEverythingFetched() const; // completing the fetch once per session should be sufficient @@ -68,10 +68,27 @@ public: bool isBulkFetchProcessingComplete() const; void setAllFoldersFetched(); - void addRequestAtFront(const LLUUID & id, BOOL recursive, bool is_category); - void addRequestAtBack(const LLUUID & id, BOOL recursive, bool is_category); + void addRequestAtFront(const LLUUID & id, bool recursive, bool is_category); + void addRequestAtBack(const LLUUID & id, bool recursive, bool is_category); protected: + + struct FetchQueueInfo + { + FetchQueueInfo(const LLUUID& id, bool recursive, bool is_category = true) + : mUUID(id), + mIsCategory(is_category), + mRecursive(recursive) + {} + + LLUUID mUUID; + bool mIsCategory; + bool mRecursive; + }; + typedef std::deque fetch_queue_t; + + void bulkFetchViaAis(); + void bulkFetchViaAis(const FetchQueueInfo& fetch_info); void bulkFetch(); void backgroundFetch(); @@ -80,31 +97,19 @@ protected: bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const; private: - BOOL mRecursiveInventoryFetchStarted; - BOOL mRecursiveLibraryFetchStarted; - BOOL mAllFoldersFetched; + bool mRecursiveInventoryFetchStarted; + bool mRecursiveLibraryFetchStarted; + bool mAllFoldersFetched; - BOOL mBackgroundFetchActive; + bool mBackgroundFetchActive; bool mFolderFetchActive; S32 mFetchCount; LLFrameTimer mFetchTimer; F32 mMinTimeBetweenFetches; - - struct FetchQueueInfo - { - FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) - : mUUID(id), - mIsCategory(is_category), - mRecursive(recursive) - {} - - LLUUID mUUID; - bool mIsCategory; - BOOL mRecursive; - }; - typedef std::deque fetch_queue_t; fetch_queue_t mFetchQueue; + fetch_queue_t mRecursiveFetchQueue; + }; #endif // LL_LLINVENTORYMODELBACKGROUNDFETCH_H diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 776b9f8279..842192a62b 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1897,6 +1897,7 @@ bool idle_startup() LLNotificationsUtil::add("InventoryUnusable"); } + LLInventoryModelBackgroundFetch::instance().start(); gInventory.createCommonSystemCategories(); // It's debatable whether this flag is a good idea - sets all diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 6f7c5d96f5..61123e65d7 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -667,7 +667,7 @@ bool LLViewerInventoryCategory::fetch() { LL_WARNS(LOG_INV) << "agent region is null" << LL_ENDL; } - if (!url.empty()) //Capability found. Build up LLSD and use it. + if (!url.empty() || AISAPI::isAvailable()) { LLInventoryModelBackgroundFetch::instance().start(mUUID, false); } -- cgit v1.3 From 83811ff846d9c046e694708c209a6d4dc0bb45a3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 15 Mar 2023 03:29:03 +0200 Subject: SL-18629 WIP Fetch Inventory using AIS caps #2 --- indra/newview/llaisapi.cpp | 113 +++++++-------- indra/newview/llaisapi.h | 1 - indra/newview/llinventorymodelbackgroundfetch.cpp | 164 ++++++++++++++-------- indra/newview/llinventorymodelbackgroundfetch.h | 10 +- 4 files changed, 164 insertions(+), 124 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 87811e9c0b..23bb123dee 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -483,41 +483,6 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r EnqueueAISCommand("FetchCategoryCategories", proc); } -/*static*/ -void AISAPI::FetchCOF(completion_t callback) -{ - std::string cap; - cap = getInvCap(); - if (cap.empty()) - { - LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; - return; - } - LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - - std::string url = cap + std::string("/category/") + cof_id.asString() + "/links"; - - //LLUUID root_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_ROOT_INVENTORY); - //std::string url = cap + std::string("/category/") + root_id.asString() + "/children?depth=*"; - - invokationFn_t patchFn = 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, patchFn, url, cof_id, LLSD(), callback, FETCHCOF)); - - EnqueueAISCommand("FetchCOF", proc); -} - /*static*/ void AISAPI::EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc) { @@ -578,8 +543,7 @@ void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, CO } bool is_fetch = (type == FETCHITEM) || (type == FETCHCATEGORYCHILDREN) - || (type == FETCHCATEGORYCATEGORIES) - || (type == FETCHCOF); + || (type == FETCHCATEGORYCATEGORIES); // parse update llsd into stuff to do or parse received items. AISUpdate ais_update(update, is_fetch); ais_update.doUpdate(); // execute the updates in the appropriate order. @@ -648,36 +612,16 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } } } - /*else if (status.getType() == 403) + else if (status.getType() == 403) { if (type == FETCHCATEGORYCHILDREN) { - if (url.find("?depth=*") != std::string::npos) - { - LL_WARNS() << "too much" << LL_ENDL; - AISAPI::FetchCategoryChildren(gInventory.getRootFolderID(), AISAPI::ITEM_TYPE::INVENTORY, false, boost::bind(&LLInventoryModel::fetchDescendentsDepthOne, &gInventory, targetId)); - - if (result["oversize_inventory"].asBoolean() == true) - { - LL_WARNS("Inventory") << "Can't fetch the oversized inventory folder" << LL_ENDL; - } - } - else - { - if (result["oversize_inventory"].asBoolean() == true) - { - LL_WARNS("Inventory") << "Can't fetch the oversized inventory folder" << LL_ENDL; - } - } + LL_DEBUGS("Inventory") << "Fetch failed, content is over imit" << LL_ENDL; } - }*/ + } LL_WARNS("Inventory") << "Inventory error: " << status.toString() << LL_ENDL; LL_WARNS("Inventory") << ll_pretty_print_sd(result) << LL_ENDL; } - else if (type == FETCHCOF) - { - //LL_WARNS("Inventory") << ll_pretty_print_sd(result) << LL_ENDL; - } LL_DEBUGS("Inventory") << result << LL_ENDL; onUpdateReceived("AISCommand", result, type); @@ -687,7 +631,10 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht bool needs_callback = true; LLUUID id(LLUUID::null); - if (type == COPYLIBRARYCATEGORY && result.has("category_id")) + if ( ( (type == COPYLIBRARYCATEGORY) + || (type == FETCHCATEGORYCATEGORIES) + || (type == FETCHCATEGORYCHILDREN)) + && result.has("category_id")) { id = result["category_id"]; } @@ -871,7 +818,12 @@ void AISUpdate::parseItem(const LLSD& item_map) BOOL rv = new_item->unpackMessage(item_map); if (rv) { - if (!mFetch && curr_item) + if (mFetch) + { + mItemsCreated[item_id] = new_item; + mCatDescendentDeltas[new_item->getParentUUID()]; + } + else if (curr_item) { mItemsUpdated[item_id] = new_item; // This statement is here to cause a new entry with 0 @@ -906,7 +858,19 @@ void AISUpdate::parseLink(const LLSD& link_map) if (rv) { const LLUUID& parent_id = new_link->getParentUUID(); - if (!mFetch && curr_link) + if (mFetch) + { + LLPermissions default_perms; + default_perms.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); + default_perms.initMasks(PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE); + new_link->setPermissions(default_perms); + LLSaleInfo default_sale_info; + new_link->setSaleInfo(default_sale_info); + //LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << LL_ENDL; + mItemsCreated[item_id] = new_link; + mCatDescendentDeltas[parent_id]; + } + else if (curr_link) { mItemsUpdated[item_id] = new_link; // This statement is here to cause a new entry with 0 @@ -973,7 +937,28 @@ void AISUpdate::parseCategory(const LLSD& category_map) //} if (rv) { - if (curr_cat && !mFetch) + if (mFetch) + { + // Set version/descendents for newly created categories. + if (category_map.has("version")) + { + S32 version = category_map["version"].asInteger(); + LL_DEBUGS("Inventory") << "Setting version to " << version + << " for new category " << category_id << LL_ENDL; + new_cat->setVersion(version); + } + uuid_int_map_t::const_iterator lookup_it = mCatDescendentsKnown.find(category_id); + if (mCatDescendentsKnown.end() != lookup_it) + { + S32 descendent_count = lookup_it->second; + LL_DEBUGS("Inventory") << "Setting descendents count to " << descendent_count + << " for new category " << category_id << LL_ENDL; + new_cat->setDescendentCount(descendent_count); + } + mCategoriesCreated[category_id] = new_cat; + mCatDescendentDeltas[new_cat->getParentUUID()]; + } + else if (curr_cat) { mCategoriesUpdated[category_id] = new_cat; // This statement is here to cause a new entry with 0 diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 3de3366a0e..58f6a17650 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -75,7 +75,6 @@ private: FETCHITEM, FETCHCATEGORYCHILDREN, FETCHCATEGORYCATEGORIES, - FETCHCOF, } COMMAND_TYPE; static const std::string INVENTORY_CAP_NAME; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 1905a9c9a4..5ea8fe4cba 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -244,12 +244,14 @@ BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, bool recursive, bool is_category) { - mFetchQueue.push_front(FetchQueueInfo(id, recursive, is_category)); + ERecursionType recursion_type = recursive ? RT_RECURSIVE : RT_NONE; + mFetchQueue.push_front(FetchQueueInfo(id, recursion_type, is_category)); } void LLInventoryModelBackgroundFetch::addRequestAtBack(const LLUUID & id, bool recursive, bool is_category) { - mFetchQueue.push_back(FetchQueueInfo(id, recursive, is_category)); + ERecursionType recursion_type = recursive ? RT_RECURSIVE : RT_NONE; + mFetchQueue.push_back(FetchQueueInfo(id, recursion_type, is_category)); } void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) @@ -263,6 +265,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) mBackgroundFetchActive = true; mFolderFetchActive = true; + ERecursionType recursion_type = recursive ? RT_RECURSIVE : RT_NONE; if (id.isNull()) { if (! mRecursiveInventoryFetchStarted) @@ -270,11 +273,14 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) mRecursiveInventoryFetchStarted |= recursive; if (recursive && AISAPI::isAvailable()) { - mRecursiveFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); + // Not only root folder can be massive, but + // most system folders will be requested independently + // so request root folder and content separately + mRecursiveFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), RT_CONTENT)); } else { - mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); + mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursion_type)); } gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } @@ -283,11 +289,11 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) mRecursiveLibraryFetchStarted |= recursive; if (recursive && AISAPI::isAvailable()) { - mRecursiveFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); + mRecursiveFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursion_type)); } else { - mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); + mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursion_type)); } gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } @@ -299,7 +305,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) // AIS does depth requests, recursive requests will need to be prioritizes if (mRecursiveFetchQueue.empty() || mRecursiveFetchQueue.back().mUUID != id) { - mRecursiveFetchQueue.push_back(FetchQueueInfo(id, recursive)); + mRecursiveFetchQueue.push_back(FetchQueueInfo(id, recursion_type)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } @@ -308,7 +314,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) // Specific folder requests go to front of queue. if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id) { - mFetchQueue.push_front(FetchQueueInfo(id, recursive)); + mFetchQueue.push_front(FetchQueueInfo(id, recursion_type)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } @@ -328,7 +334,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) { mBackgroundFetchActive = true; - mFetchQueue.push_front(FetchQueueInfo(id, false, false)); + mFetchQueue.push_front(FetchQueueInfo(id, RT_NONE, false)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } @@ -338,7 +344,7 @@ void LLInventoryModelBackgroundFetch::findLostItems() { mBackgroundFetchActive = true; mFolderFetchActive = true; - mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, true)); + mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, RT_RECURSIVE)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } @@ -386,11 +392,45 @@ void LLInventoryModelBackgroundFetch::incrFetchCount(S32 fetching) mFetchCount = 0; } } -void ais_callback(const LLUUID& inv_id) + +void ais_simple_callback(const LLUUID& inv_id) { LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } +void LLInventoryModelBackgroundFetch::onAISCalback(const LLUUID &request_id, const LLUUID &response_id, ERecursionType recursion) +{ + incrFetchCount(-1); + if (response_id.isNull()) // Failure + { + if (recursion == RT_RECURSIVE) + { + // A full recursive request failed. + // Try requesting folder and nested content separately + mBackgroundFetchActive = true; + mFolderFetchActive = true; + mRecursiveFetchQueue.push_back(FetchQueueInfo(request_id, RT_CONTENT)); + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + } + } + else + { + if (recursion == RT_CONTENT) + { + // Got the folder, now recursively request content + LLInventoryModel::cat_array_t * categories(NULL); + LLInventoryModel::item_array_t * items(NULL); + gInventory.getDirectDescendentsOf(request_id, categories, items); + for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); + it != categories->end(); + ++it) + { + mRecursiveFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), RT_RECURSIVE)); + } + } + } +} + static LLTrace::BlockTimerStatHandle FTM_BULK_FETCH("Bulk Fetch"); void LLInventoryModelBackgroundFetch::bulkFetchViaAis() @@ -438,45 +478,54 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc const LLUUID & cat_id(fetch_info.mUUID); if (cat_id.isNull()) // Lost and found { - AISAPI::FetchCategoryChildren(LLUUID::null, AISAPI::INVENTORY, false, ais_callback); + AISAPI::FetchCategoryChildren(LLUUID::null, AISAPI::INVENTORY, false, ais_simple_callback); mFetchCount++; } else { - const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); - if (cat) + if (!gInventory.isCategoryComplete(cat_id)) { - if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) + const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); + if (cat) { if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) { - AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::LIBRARY, fetch_info.mRecursive, ais_callback); + AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::LIBRARY, fetch_info.mRecursive == RT_RECURSIVE, ais_simple_callback); } else { - AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::INVENTORY, fetch_info.mRecursive, ais_callback); + LLUUID cat_id = cat->getUUID(); + ERecursionType type = fetch_info.mRecursive; + AISAPI::FetchCategoryChildren( + cat_id, + AISAPI::INVENTORY, + type == RT_RECURSIVE, + [cat_id, type](const LLUUID &response_id) + { + LLInventoryModelBackgroundFetch::instance().onAISCalback(cat_id, response_id, type); + }); } mFetchCount++; } - else + // else? + } + else + { + // Already fetched, check if anything inside needs fetching + if (fetch_info.mRecursive) { - // Already fetched, check if anything inside needs fetching - if (fetch_info.mRecursive) + LLInventoryModel::cat_array_t * categories(NULL); + LLInventoryModel::item_array_t * items(NULL); + gInventory.getDirectDescendentsOf(cat_id, categories, items); + for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); + it != categories->end(); + ++it) { - LLInventoryModel::cat_array_t * categories(NULL); - LLInventoryModel::item_array_t * items(NULL); - gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); - for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); - it != categories->end(); - ++it) - { - mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); - } + mRecursiveFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); } } } - // else??? } } else @@ -487,11 +536,11 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc { if (itemp->getPermissions().getOwner() == gAgent.getID()) { - AISAPI::FetchItem(itemp->getUUID(), AISAPI::INVENTORY, ais_callback); + AISAPI::FetchItem(itemp->getUUID(), AISAPI::INVENTORY, ais_simple_callback); } else { - AISAPI::FetchItem(itemp->getUUID(), AISAPI::LIBRARY, ais_callback); + AISAPI::FetchItem(itemp->getUUID(), AISAPI::LIBRARY, ais_simple_callback); } mFetchCount++; } @@ -576,36 +625,37 @@ void LLInventoryModelBackgroundFetch::bulkFetch() } else { - const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); - - if (cat) - { - if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) - { - LLSD folder_sd; - folder_sd["folder_id"] = cat->getUUID(); - folder_sd["owner_id"] = cat->getOwnerID(); - folder_sd["sort_order"] = LLSD::Integer(sort_order); - folder_sd["fetch_folders"] = LLSD::Boolean(true); //(LLSD::Boolean)sFullFetchStarted; - folder_sd["fetch_items"] = LLSD::Boolean(true); - - if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) - { - folder_request_body_lib["folders"].append(folder_sd); - } - else - { - folder_request_body["folders"].append(folder_sd); - } - folder_count++; - } - + if (!gInventory.isCategoryComplete(cat_id)) + { + const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); + if (cat) + { + LLSD folder_sd; + folder_sd["folder_id"] = cat->getUUID(); + folder_sd["owner_id"] = cat->getOwnerID(); + folder_sd["sort_order"] = LLSD::Integer(sort_order); + folder_sd["fetch_folders"] = LLSD::Boolean(true); //(LLSD::Boolean)sFullFetchStarted; + folder_sd["fetch_items"] = LLSD::Boolean(true); + + if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) + { + folder_request_body_lib["folders"].append(folder_sd); + } + else + { + folder_request_body["folders"].append(folder_sd); + } + folder_count++; + } + } + else + { // May already have this folder, but append child folders to list. if (fetch_info.mRecursive) { LLInventoryModel::cat_array_t * categories(NULL); LLInventoryModel::item_array_t * items(NULL); - gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); + gInventory.getDirectDescendentsOf(cat_id, categories, items); for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); it != categories->end(); ++it) diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index ac1c42e0d7..4c4de6ac7c 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -73,9 +73,14 @@ public: protected: + typedef enum { + RT_NONE = 0, + RT_CONTENT, // request content recursively + RT_RECURSIVE, // request everything recursively + } ERecursionType; struct FetchQueueInfo { - FetchQueueInfo(const LLUUID& id, bool recursive, bool is_category = true) + FetchQueueInfo(const LLUUID& id, ERecursionType recursive, bool is_category = true) : mUUID(id), mIsCategory(is_category), mRecursive(recursive) @@ -83,10 +88,11 @@ protected: LLUUID mUUID; bool mIsCategory; - bool mRecursive; + ERecursionType mRecursive; }; typedef std::deque fetch_queue_t; + void onAISCalback(const LLUUID &request_id, const LLUUID &response_id, ERecursionType recursion); void bulkFetchViaAis(); void bulkFetchViaAis(const FetchQueueInfo& fetch_info); void bulkFetch(); -- cgit v1.3 From 7a70d93c437a7065b0c0be7fa63d36f511a9cef2 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 15 Mar 2023 20:03:53 +0200 Subject: SL-18629 Fetch Inventory using AIS caps #3 --- indra/newview/llaisapi.cpp | 28 ++++++++++--- indra/newview/llinventorymodelbackgroundfetch.cpp | 50 ++++++++--------------- indra/newview/llinventorymodelbackgroundfetch.h | 1 - 3 files changed, 39 insertions(+), 40 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 23bb123dee..bb963d77c9 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -901,7 +901,25 @@ void AISUpdate::parseLink(const LLSD& link_map) void AISUpdate::parseCategory(const LLSD& category_map) { - LLUUID category_id = category_map["category_id"].asUUID(); + LLUUID category_id = category_map["category_id"].asUUID(); + S32 version = LLViewerInventoryCategory::VERSION_UNKNOWN; + + if (category_map.has("version")) + { + version = category_map["version"].asInteger(); + } + + LLViewerInventoryCategory *curr_cat = gInventory.getCategory(category_id); + + if (curr_cat + && curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN + && version > LLViewerInventoryCategory::VERSION_UNKNOWN + && version < curr_cat->getVersion()) + { + LL_WARNS() << "Got stale folder, known: " << curr_cat->getVersion() + << ", received: " << version << LL_ENDL; + return; + } // Check descendent count first, as it may be needed // to populate newly created categories @@ -911,7 +929,6 @@ void AISUpdate::parseCategory(const LLSD& category_map) } LLPointer new_cat; - LLViewerInventoryCategory *curr_cat = gInventory.getCategory(category_id); if (curr_cat) { // Default to current values where not provided. @@ -940,11 +957,10 @@ void AISUpdate::parseCategory(const LLSD& category_map) if (mFetch) { // Set version/descendents for newly created categories. - if (category_map.has("version")) + if (version > LLViewerInventoryCategory::VERSION_UNKNOWN) { - S32 version = category_map["version"].asInteger(); LL_DEBUGS("Inventory") << "Setting version to " << version - << " for new category " << category_id << LL_ENDL; + << " for category " << category_id << LL_ENDL; new_cat->setVersion(version); } uuid_int_map_t::const_iterator lookup_it = mCatDescendentsKnown.find(category_id); @@ -952,7 +968,7 @@ void AISUpdate::parseCategory(const LLSD& category_map) { S32 descendent_count = lookup_it->second; LL_DEBUGS("Inventory") << "Setting descendents count to " << descendent_count - << " for new category " << category_id << LL_ENDL; + << " for category " << category_id << LL_ENDL; new_cat->setDescendentCount(descendent_count); } mCategoriesCreated[category_id] = new_cat; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 5ea8fe4cba..098ced4ec9 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -276,7 +276,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 - mRecursiveFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), RT_CONTENT)); + mFetchQueue.push_front(FetchQueueInfo(gInventory.getRootFolderID(), RT_CONTENT)); } else { @@ -287,25 +287,18 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) if (! mRecursiveLibraryFetchStarted) { mRecursiveLibraryFetchStarted |= recursive; - if (recursive && AISAPI::isAvailable()) - { - mRecursiveFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursion_type)); - } - else - { - mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursion_type)); - } + mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursion_type)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } else { - if (recursive && AISAPI::isAvailable()) + if (AISAPI::isAvailable() && !recursive) { - // AIS does depth requests, recursive requests will need to be prioritizes - if (mRecursiveFetchQueue.empty() || mRecursiveFetchQueue.back().mUUID != id) + // Specific folder requests go to front of queue. + if (mFetchQueue.empty() || mFetchQueue.back().mUUID != id) { - mRecursiveFetchQueue.push_back(FetchQueueInfo(id, recursion_type)); + mFetchQueue.push_back(FetchQueueInfo(id, recursion_type)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } @@ -318,6 +311,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } + if (id == gInventory.getLibraryRootFolderID()) { mRecursiveLibraryFetchStarted |= recursive; @@ -409,7 +403,7 @@ void LLInventoryModelBackgroundFetch::onAISCalback(const LLUUID &request_id, con // Try requesting folder and nested content separately mBackgroundFetchActive = true; mFolderFetchActive = true; - mRecursiveFetchQueue.push_back(FetchQueueInfo(request_id, RT_CONTENT)); + mFetchQueue.push_front(FetchQueueInfo(request_id, RT_CONTENT)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } @@ -425,7 +419,13 @@ void LLInventoryModelBackgroundFetch::onAISCalback(const LLUUID &request_id, con it != categories->end(); ++it) { - mRecursiveFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), RT_RECURSIVE)); + mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), RT_RECURSIVE)); + } + if (!mFetchQueue.empty()) + { + mBackgroundFetchActive = true; + mFolderFetchActive = true; + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } } @@ -442,22 +442,13 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() return; } - static const S32 max_concurrent_fetches(12); + static const S32 max_concurrent_fetches(50); if (mFetchCount >= max_concurrent_fetches) { return; } - // Start with recursive queue since it can get multiple categories - // in a single request and might contain what other requests want - while (!mRecursiveFetchQueue.empty() && mFetchCount < max_concurrent_fetches) - { - const FetchQueueInfo & fetch_info(mRecursiveFetchQueue.front()); - bulkFetchViaAis(fetch_info); - mRecursiveFetchQueue.pop_front(); - } - while (!mFetchQueue.empty() && mFetchCount < max_concurrent_fetches) { const FetchQueueInfo & fetch_info(mFetchQueue.front()); @@ -522,7 +513,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc it != categories->end(); ++it) { - mRecursiveFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); + mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); } } } @@ -598,13 +589,6 @@ void LLInventoryModelBackgroundFetch::bulkFetch() LLSD item_request_body; LLSD item_request_body_lib; - if (!mRecursiveFetchQueue.empty()) - { - LL_DEBUGS(LOG_INV) << "Request was sheduled for AIS, using legacy" << LL_ENDL; - mFetchQueue.insert(mFetchQueue.begin(), mRecursiveFetchQueue.begin(), mRecursiveFetchQueue.end()); - mRecursiveFetchQueue.clear(); - } - while (! mFetchQueue.empty() && (item_count + folder_count) < max_batch_size) { diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 4c4de6ac7c..14557ea92d 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -114,7 +114,6 @@ private: LLFrameTimer mFetchTimer; F32 mMinTimeBetweenFetches; fetch_queue_t mFetchQueue; - fetch_queue_t mRecursiveFetchQueue; }; -- cgit v1.3 From 70d99cde5826893be4964d4673ff875320b7220f Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 17 Mar 2023 23:44:28 +0200 Subject: SL-18629 Track request depth to be able to distinguish incomplete folder reliably --- indra/newview/llaisapi.cpp | 87 ++++++++++++++--------- indra/newview/llaisapi.h | 13 ++-- indra/newview/llinventorymodelbackgroundfetch.cpp | 73 ++++++++++--------- indra/newview/llviewerinventory.cpp | 6 +- 4 files changed, 102 insertions(+), 77 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index bb963d77c9..5e243476d8 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -384,7 +384,7 @@ void AISAPI::FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callba } std::string url = cap + std::string("/item/") + itemId.asString(); - invokationFn_t patchFn = boost::bind( + invokationFn_t getFn = boost::bind( // Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload. static_cast //---- @@ -397,7 +397,7 @@ void AISAPI::FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callba (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _5, _6); LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro, - _1, patchFn, url, itemId, LLSD(), callback, FETCHITEM)); + _1, getFn, url, itemId, LLSD(), callback, FETCHITEM)); EnqueueAISCommand("FetchItem", proc); } @@ -425,7 +425,7 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec url += "?depth=" + std::to_string(depth); } - invokationFn_t patchFn = boost::bind( + invokationFn_t getFn = boost::bind( // Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload. static_cast //---- @@ -437,8 +437,11 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec // _6 -> httpHeaders (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend), _1, _2, _3, _5, _6); + // get doesn't use body, can pass additional data + LLSD body; + body["depth"] = recursive ? S32_MAX : depth; LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro, - _1, patchFn, url, catId, LLSD(), callback, FETCHCATEGORYCHILDREN)); + _1, getFn, url, catId, body, callback, FETCHCATEGORYCHILDREN)); EnqueueAISCommand("FetchCategoryChildren", proc); } @@ -465,7 +468,7 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r url += "?depth=" + std::to_string(depth); } - invokationFn_t patchFn = boost::bind( + invokationFn_t getFn = boost::bind( // Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload. static_cast //---- @@ -477,8 +480,11 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r // _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, patchFn, url, catId, LLSD(), callback, FETCHCATEGORYCATEGORIES)); + _1, getFn, url, catId, body, callback, FETCHCATEGORYCATEGORIES)); EnqueueAISCommand("FetchCategoryCategories", proc); } @@ -534,7 +540,7 @@ void AISAPI::onIdle(void *userdata) } /*static*/ -void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type) +void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type, const LLSD& request_body) { LLTimer timer; if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) @@ -545,7 +551,12 @@ void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, CO || (type == FETCHCATEGORYCHILDREN) || (type == FETCHCATEGORYCATEGORIES); // parse update llsd into stuff to do or parse received items. - AISUpdate ais_update(update, is_fetch); + S32 depth = 0; + if (is_fetch && request_body.has("depth")) + { + depth = request_body["depth"].asInteger(); + } + AISUpdate ais_update(update, is_fetch, depth); ais_update.doUpdate(); // execute the updates in the appropriate order. LL_INFOS("Inventory") << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; } @@ -559,11 +570,6 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); LLCore::HttpHeaders::ptr_t httpHeaders; - /*if (type == FETCHCATEGORYCHILDREN && (url.find("?depth=*") != std::string::npos)) - { - LL_WARNS() << "testy test start"<< LL_ENDL; - }*/ - httpOptions->setTimeout(180); LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; @@ -624,7 +630,12 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } LL_DEBUGS("Inventory") << result << LL_ENDL; - onUpdateReceived("AISCommand", result, type); + onUpdateReceived("AISCommand", result, type, body); + + if (type == FETCHITEM) + { + LL_WARNS() << "test" << LL_ENDL; + } if (callback && !callback.empty()) { @@ -638,6 +649,17 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht { id = result["category_id"]; } + if (type == FETCHITEM) + { + if (result.has("item_id")) + { + id = result["item_id"]; + } + if (result.has("linked_id")) + { + id = result["linked_id"]; + } + } if (type == CREATEINVENTORY) { // CREATEINVENTORY can have multiple callbacks @@ -676,8 +698,9 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } //------------------------------------------------------------------------- -AISUpdate::AISUpdate(const LLSD& update, bool fetch) +AISUpdate::AISUpdate(const LLSD& update, bool fetch, S32 depth) : mFetch(fetch) +, mFetchDepth(depth) { parseUpdate(update); } @@ -794,13 +817,13 @@ void AISUpdate::parseContent(const LLSD& update) if (update.has("category_id")) { - parseCategory(update); + parseCategory(update, mFetchDepth); } else { if (update.has("_embedded")) { - parseEmbedded(update["_embedded"]); + parseEmbedded(update["_embedded"], mFetchDepth); } } } @@ -899,7 +922,7 @@ void AISUpdate::parseLink(const LLSD& link_map) } -void AISUpdate::parseCategory(const LLSD& category_map) +void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) { LLUUID category_id = category_map["category_id"].asUUID(); S32 version = LLViewerInventoryCategory::VERSION_UNKNOWN; @@ -948,17 +971,17 @@ void AISUpdate::parseCategory(const LLSD& category_map) } BOOL rv = new_cat->unpackMessage(category_map); // *NOTE: unpackMessage does not unpack version or descendent count. - //if (category_map.has("version")) - //{ - // mCatVersionsUpdated[category_id] = category_map["version"].asInteger(); - //} if (rv) { if (mFetch) { - // Set version/descendents for newly created categories. - if (version > LLViewerInventoryCategory::VERSION_UNKNOWN) + // set version only if previous one was already known + // or if we are sure this update has full data and embeded items (depth 0+) + // since bulk fetch uses this to decide what still needs fetching + if (version > LLViewerInventoryCategory::VERSION_UNKNOWN + && (depth >= 0 || (curr_cat && curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN))) { + // Set version/descendents for newly fetched categories. LL_DEBUGS("Inventory") << "Setting version to " << version << " for category " << category_id << LL_ENDL; new_cat->setVersion(version); @@ -1015,7 +1038,7 @@ void AISUpdate::parseCategory(const LLSD& category_map) // Check for more embedded content. if (category_map.has("_embedded")) { - parseEmbedded(category_map["_embedded"]); + parseEmbedded(category_map["_embedded"], depth - 1); } } @@ -1032,7 +1055,7 @@ void AISUpdate::parseDescendentCount(const LLUUID& category_id, const LLSD& embe } } -void AISUpdate::parseEmbedded(const LLSD& embedded) +void AISUpdate::parseEmbedded(const LLSD& embedded, S32 depth) { if (embedded.has("links")) // _embedded in a category { @@ -1048,11 +1071,11 @@ void AISUpdate::parseEmbedded(const LLSD& embedded) } if (embedded.has("categories")) // _embedded in a category { - parseEmbeddedCategories(embedded["categories"]); + parseEmbeddedCategories(embedded["categories"], depth); } if (embedded.has("category")) // _embedded in a link { - parseEmbeddedCategory(embedded["category"]); + parseEmbeddedCategory(embedded["category"], depth); } } @@ -1120,19 +1143,19 @@ void AISUpdate::parseEmbeddedItems(const LLSD& items) } } -void AISUpdate::parseEmbeddedCategory(const LLSD& category) +void AISUpdate::parseEmbeddedCategory(const LLSD& category, S32 depth) { // a single category (_embedded in a link) if (category.has("category_id")) { if (mFetch || mCategoryIds.end() != mCategoryIds.find(category["category_id"].asUUID())) { - parseCategory(category); + parseCategory(category, depth); } } } -void AISUpdate::parseEmbeddedCategories(const LLSD& categories) +void AISUpdate::parseEmbeddedCategories(const LLSD& categories, S32 depth) { // a map of categories (_embedded in a category) for(LLSD::map_const_iterator categoryit = categories.beginMap(), @@ -1147,7 +1170,7 @@ void AISUpdate::parseEmbeddedCategories(const LLSD& categories) } else { - parseCategory(category_map); + parseCategory(category_map, depth); } } } diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 58f6a17650..93bbbedb3b 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -85,7 +85,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); + static void onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type, const LLSD& request_body); static std::string getInvCap(); static std::string getLibCap(); @@ -101,21 +101,21 @@ private: class AISUpdate { public: - AISUpdate(const LLSD& update, bool fetch); + AISUpdate(const LLSD& update, bool fetch, S32 depth); 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 parseItem(const LLSD& link_map); - void parseCategory(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); + void parseEmbedded(const LLSD& embedded, S32 depth); void parseEmbeddedLinks(const LLSD& links); void parseEmbeddedItems(const LLSD& items); - void parseEmbeddedCategories(const LLSD& categories); + void parseEmbeddedCategories(const LLSD& categories, S32 depth); void parseEmbeddedItem(const LLSD& item); - void parseEmbeddedCategory(const LLSD& category); + void parseEmbeddedCategory(const LLSD& category, S32 depth); void doUpdate(); private: void clearParseResults(); @@ -138,6 +138,7 @@ private: uuid_list_t mItemIds; uuid_list_t mCategoryIds; bool mFetch; + S32 mFetchDepth; }; #endif diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 282d234cf3..6cae035fcf 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -478,10 +478,10 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc else { - if (!gInventory.isCategoryComplete(cat_id)) + const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); + if (cat) { - const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); - if (cat) + if (!gInventory.isCategoryComplete(cat_id)) { if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) { @@ -502,25 +502,24 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc } mFetchCount++; } - // else? - } - else - { - // Already fetched, check if anything inside needs fetching - if (fetch_info.mRecursive) + else { - LLInventoryModel::cat_array_t * categories(NULL); - LLInventoryModel::item_array_t * items(NULL); - gInventory.getDirectDescendentsOf(cat_id, categories, items); - for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); - it != categories->end(); - ++it) + // Already fetched, check if anything inside needs fetching + if (fetch_info.mRecursive) { - // not push_front to not cause an infinite loop - mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); + LLInventoryModel::cat_array_t * categories(NULL); + LLInventoryModel::item_array_t * items(NULL); + gInventory.getDirectDescendentsOf(cat_id, categories, items); + for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); + it != categories->end(); + ++it) + { + // not push_front to not cause an infinite loop + mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); + } } } - } + } // else? } } else @@ -613,10 +612,10 @@ void LLInventoryModelBackgroundFetch::bulkFetch() } else { - if (!gInventory.isCategoryComplete(cat_id)) + const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); + if (cat) { - const LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); - if (cat) + if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) { LLSD folder_sd; folder_sd["folder_id"] = cat->getUUID(); @@ -635,23 +634,23 @@ void LLInventoryModelBackgroundFetch::bulkFetch() } folder_count++; } + else + { + // May already have this folder, but append child folders to list. + if (fetch_info.mRecursive) + { + LLInventoryModel::cat_array_t * categories(NULL); + LLInventoryModel::item_array_t * items(NULL); + gInventory.getDirectDescendentsOf(cat_id, categories, items); + for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); + it != categories->end(); + ++it) + { + mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); + } + } + } } - else - { - // May already have this folder, but append child folders to list. - if (fetch_info.mRecursive) - { - LLInventoryModel::cat_array_t * categories(NULL); - LLInventoryModel::item_array_t * items(NULL); - gInventory.getDirectDescendentsOf(cat_id, categories, items); - for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); - it != categories->end(); - ++it) - { - mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); - } - } - } } if (fetch_info.mRecursive) { diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 07338b7b6b..2f2bc3f91f 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1928,11 +1928,13 @@ const LLUUID& LLViewerInventoryItem::getThumbnailUUID() const } if (mThumbnailUUID.isNull() && mType == LLAssetType::AT_LINK) { - return gInventory.getItem(getLinkedUUID())->getThumbnailUUID(); + LLViewerInventoryItem *linked_item = gInventory.getItem(mAssetUUID); + return linked_item ? linked_item->getThumbnailUUID() : LLUUID::null; } if (mThumbnailUUID.isNull() && mType == LLAssetType::AT_LINK_FOLDER) { - return gInventory.getCategory(getLinkedUUID())->getThumbnailUUID(); + LLViewerInventoryCategory *linked_cat = gInventory.getCategory(mAssetUUID); + return linked_cat ? linked_cat->getThumbnailUUID() : LLUUID::null; } return mThumbnailUUID; } -- cgit v1.3 From f98c1403fb47990181c504acfbf5d35a393225b7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 18 Mar 2023 01:15:27 +0200 Subject: SL-18674 Reenable folder creation via AIS v3 Add item fetching via AIS v3 --- indra/newview/llaisapi.cpp | 5 --- indra/newview/llaisapi.h | 1 - indra/newview/llinventorymodel.cpp | 3 +- indra/newview/llviewerinventory.cpp | 89 ++++++++++++++++++++----------------- 4 files changed, 49 insertions(+), 49 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 5e243476d8..ece03d6988 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -632,11 +632,6 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht LL_DEBUGS("Inventory") << result << LL_ENDL; onUpdateReceived("AISCommand", result, type, body); - if (type == FETCHITEM) - { - LL_WARNS() << "test" << LL_ENDL; - } - if (callback && !callback.empty()) { bool needs_callback = true; diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 93bbbedb3b..dd02951cd4 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -58,7 +58,6 @@ public: static void FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callback = completion_t()); 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 FetchCategoryCategories(const LLUUID &catId, 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 CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t()); private: diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 43bfaf454c..52121d644f 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -996,7 +996,6 @@ void 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. @@ -1047,7 +1046,7 @@ void LLInventoryModel::createNewCategory(const LLUUID& parent_id, }); return; } -#endif + LLViewerRegion* viewer_region = gAgent.getRegion(); std::string url; if ( viewer_region ) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 2f2bc3f91f..6f18d72be0 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -430,48 +430,50 @@ void LLViewerInventoryItem::fetchFromServer(void) const { if(!mIsComplete) { - std::string url; + if (AISAPI::isAvailable()) // AIS v 3 + { + if (gAgent.getID() != mPermissions.getOwner()) + { + AISAPI::FetchItem(mUUID, AISAPI::LIBRARY); + } + else + { + AISAPI::FetchItem(mUUID, AISAPI::INVENTORY); + } + } + else + { + std::string url; - LLViewerRegion* region = gAgent.getRegion(); - // we have to check region. It can be null after region was destroyed. See EXT-245 - if (region) - { - if (gAgent.getID() != mPermissions.getOwner()) - { - url = region->getCapability("FetchLib2"); - } - else - { - url = region->getCapability("FetchInventory2"); - } - } - else - { - LL_WARNS(LOG_INV) << "Agent Region is absent" << LL_ENDL; - } + LLViewerRegion* region = gAgent.getRegion(); + // we have to check region. It can be null after region was destroyed. See EXT-245 + if (region) + { + if (gAgent.getID() != mPermissions.getOwner()) + { + url = region->getCapability("FetchLib2"); + } + else + { + url = region->getCapability("FetchInventory2"); + } + } + else + { + LL_WARNS(LOG_INV) << "Agent Region is absent" << LL_ENDL; + } - if (!url.empty()) - { - LLSD body; - body["agent_id"] = gAgent.getID(); - body["items"][0]["owner_id"] = mPermissions.getOwner(); - body["items"][0]["item_id"] = mUUID; + if (!url.empty()) + { + LLSD body; + body["agent_id"] = gAgent.getID(); + body["items"][0]["owner_id"] = mPermissions.getOwner(); + body["items"][0]["item_id"] = mUUID; - LLCore::HttpHandler::ptr_t handler(new LLInventoryModel::FetchItemHttpHandler(body)); - gInventory.requestPost(true, url, body, handler, "Inventory Item"); - } - else - { - LLMessageSystem* msg = gMessageSystem; - msg->newMessage("FetchInventory"); - msg->nextBlock("AgentData"); - msg->addUUID("AgentID", gAgent.getID()); - msg->addUUID("SessionID", gAgent.getSessionID()); - msg->nextBlock("InventoryData"); - msg->addUUID("OwnerID", mPermissions.getOwner()); - msg->addUUID("ItemID", mUUID); - gAgent.sendReliableMessage(); - } + LLCore::HttpHandler::ptr_t handler(new LLInventoryModel::FetchItemHttpHandler(body)); + gInventory.requestPost(true, url, body, handler, "Inventory Item"); + } + } } } @@ -1033,7 +1035,7 @@ void create_inventory_item( } #ifdef USE_AIS_FOR_NC - // D567 currently this doesn't work due to missing AIS3 support + // D567 18.03.2023 not yet implemented within AIS3 if (AISAPI::isAvailable()) { LLSD new_inventory = LLSD::emptyMap(); @@ -1067,12 +1069,17 @@ void create_inventory_item( 0 /*don't know yet, whenever server creates it*/); LLSD item_sd = item->asLLSD(); new_inventory["items"].append(item_sd); + AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1); AISAPI::CreateInventory( parent_id, new_inventory, - nullptr); + cr); return; } + else + { + LL_WARNS() << "AIS v3 not available" << LL_ENDL; + } #endif LLMessageSystem* msg = gMessageSystem; -- 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/llaisapi.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 04501955c7d0cd19d13ac1374f6f06e944f6ea61 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 23 Mar 2023 21:13:30 +0200 Subject: SL-19108 Disable "Image" button for task inventories Thumbnails are not supported for task inventories yet --- indra/newview/llaisapi.cpp | 5 +++-- indra/newview/llinventorymodel.cpp | 4 ++++ indra/newview/llsidepaneliteminfo.cpp | 8 ++++++-- indra/newview/llsidepaneliteminfo.h | 5 +++-- 4 files changed, 16 insertions(+), 6 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index d2bf7a0e9a..d0c8d38e28 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -543,7 +543,8 @@ void AISAPI::onIdle(void *userdata) void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type, const LLSD& request_body) { LLTimer timer; - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + if ( (type == UPDATECATEGORY || type == UPDATEITEM) + && gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { dump_sequential_xml(gAgentAvatarp->getFullname() + "_ais_update", update); } @@ -558,7 +559,7 @@ void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, CO } AISUpdate ais_update(update, is_fetch, depth); ais_update.doUpdate(); // execute the updates in the appropriate order. - LL_INFOS("Inventory") << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; + LL_DEBUGS("Inventory") << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; } /*static*/ diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index b833571ee9..6d9142cc5c 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3448,6 +3448,10 @@ void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, vo msg->getU32Fast(_PREHASH_InventoryData, _PREHASH_CallbackID, callback_id); gInventoryCallbacks.fire(callback_id, item_id); + + // todo: instead of unpacking message fully, + // grab only an item_id, then fetch via AIS + AISAPI::FetchItem(item_id, AISAPI::INVENTORY); } } diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp index 312dee8c93..9660fa5916 100644 --- a/indra/newview/llsidepaneliteminfo.cpp +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -154,15 +154,16 @@ LLSidepanelItemInfo::~LLSidepanelItemInfo() // virtual BOOL LLSidepanelItemInfo::postBuild() { + mChangeThumbnailBtn = getChild("change_thumbnail_btn"); + mItemTypeIcon = getChild("item_type_icon"); mLabelOwnerName = getChild("LabelOwnerName"); mLabelCreatorName = getChild("LabelCreatorName"); - mItemTypeIcon = getChild("item_type_icon"); getChild("LabelItemName")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); getChild("LabelItemName")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onCommitName,this)); getChild("LabelItemDesc")->setCommitCallback(boost::bind(&LLSidepanelItemInfo:: onCommitDescription, this)); // Thumnail edition - getChild("change_thumbnail_btn")->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onEditThumbnail, this)); + mChangeThumbnailBtn->setCommitCallback(boost::bind(&LLSidepanelItemInfo::onEditThumbnail, this)); // acquired date // owner permissions // Permissions debug text @@ -443,6 +444,9 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item) mLabelOwnerName->setEnabled(FALSE); mLabelOwnerName->setValue(getString("public")); } + + // Not yet supported for task inventories + mChangeThumbnailBtn->setEnabled(mObjectID.isNull()); //////////// // ORIGIN // diff --git a/indra/newview/llsidepaneliteminfo.h b/indra/newview/llsidepaneliteminfo.h index ba1d5c263a..b916f44520 100644 --- a/indra/newview/llsidepaneliteminfo.h +++ b/indra/newview/llsidepaneliteminfo.h @@ -100,10 +100,11 @@ private: S32 mUpdatePendingId; bool mIsDirty; // item properties need to be updated LLFloater* mParentFloater; - + + LLUICtrl* mChangeThumbnailBtn; + LLIconCtrl* mItemTypeIcon; LLTextBox* mLabelOwnerName; LLTextBox* mLabelCreatorName; - LLIconCtrl* mItemTypeIcon; // // UI Elements -- cgit v1.3 From 9fa64f1e2087a8e45adad7298d2dd3661bd80e25 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 24 Mar 2023 18:03:09 +0200 Subject: SL-18003 Fix items not being marked as complete when fetched via ais --- indra/newview/llaisapi.cpp | 1 + indra/newview/llinventoryfilter.cpp | 3 ++- indra/newview/llinventorymodel.cpp | 6 +++--- indra/newview/llinventoryobserver.cpp | 2 +- indra/newview/llsidepaneliteminfo.cpp | 2 +- indra/newview/llviewerinventory.cpp | 8 ++++---- indra/newview/llviewerinventory.h | 6 +++--- 7 files changed, 15 insertions(+), 13 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index d0c8d38e28..d204a752ec 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -845,6 +845,7 @@ void AISUpdate::parseItem(const LLSD& item_map) { mItemsCreated[item_id] = new_item; mCatDescendentDeltas[new_item->getParentUUID()]; + new_item->setComplete(true); } else if (curr_item) { diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 6e09161473..0af383f232 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -195,7 +195,8 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const // when applying a filter, matching folders get their contents downloaded first // but make sure we are not interfering with pre-download if (isNotDefault() - && LLStartUp::getStartupState() > STATE_WEARABLES_WAIT) + && LLStartUp::getStartupState() > STATE_WEARABLES_WAIT + && !LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress()) { LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id); if (!cat || (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)) diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 56f0a68f70..4c2383d211 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3451,7 +3451,7 @@ void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, vo // todo: instead of unpacking message fully, // grab only an item_id, then fetch via AIS - AISAPI::FetchItem(item_id, AISAPI::INVENTORY); + LLInventoryModelBackgroundFetch::instance().start(item_id, false); } } @@ -3795,7 +3795,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 - AISAPI::FetchCategoryChildren((*cit)->getUUID(), AISAPI::INVENTORY); + LLInventoryModelBackgroundFetch::instance().start((*cit)->getUUID(), false); } for (item_array_t::iterator iit = items.begin(); iit != items.end(); ++iit) { @@ -3804,7 +3804,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 - AISAPI::FetchItem((*iit)->getUUID(), AISAPI::INVENTORY); + LLInventoryModelBackgroundFetch::instance().start((*iit)->getUUID(), false); } gInventory.notifyObservers(); diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 809fbe4100..25f1854765 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -310,7 +310,7 @@ void LLInventoryFetchItemsObserver::startFetch() } // Todo: remove item from mIncomplete on callback // but keep in mind that observer can expire before - // callback + // callback or use LLInventoryModelBackgroundFetch } else { diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp index 9660fa5916..48e610a135 100644 --- a/indra/newview/llsidepaneliteminfo.cpp +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -280,7 +280,7 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item) } // do not enable the UI for incomplete items. - BOOL is_complete = item->isFinished(); + bool is_complete = item->isFinished(); const BOOL cannot_restrict_permissions = LLInventoryType::cannotRestrictPermissions(item->getInventoryType()); const BOOL is_calling_card = (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD); const BOOL is_settings = (item->getInventoryType() == LLInventoryType::IT_SETTINGS); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 95174c75e9..d8de269c3c 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -312,7 +312,7 @@ LLViewerInventoryItem::LLViewerInventoryItem(const LLUUID& uuid, time_t creation_date_utc) : LLInventoryItem(uuid, parent_uuid, perm, asset_uuid, type, inv_type, name, desc, sale_info, flags, creation_date_utc), - mIsComplete(TRUE) + mIsComplete(true) { } @@ -321,7 +321,7 @@ LLViewerInventoryItem::LLViewerInventoryItem(const LLUUID& item_id, const std::string& name, LLInventoryType::EType inv_type) : LLInventoryItem(), - mIsComplete(FALSE) + mIsComplete(false) { mUUID = item_id; mParentUUID = parent_id; @@ -331,7 +331,7 @@ LLViewerInventoryItem::LLViewerInventoryItem(const LLUUID& item_id, LLViewerInventoryItem::LLViewerInventoryItem() : LLInventoryItem(), - mIsComplete(FALSE) + mIsComplete(false) { } @@ -348,7 +348,7 @@ LLViewerInventoryItem::LLViewerInventoryItem(const LLViewerInventoryItem* other) LLViewerInventoryItem::LLViewerInventoryItem(const LLInventoryItem *other) : LLInventoryItem(other), - mIsComplete(TRUE) + mIsComplete(true) { } diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 63f163b168..1554c84137 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -135,8 +135,8 @@ public: virtual BOOL importLegacyStream(std::istream& input_stream); // new methods - BOOL isFinished() const { return mIsComplete; } - void setComplete(BOOL complete) { mIsComplete = complete; } + bool isFinished() const { return mIsComplete; } + void setComplete(bool complete) { mIsComplete = complete; } //void updateAssetOnServer() const; virtual void setTransactionID(const LLTransactionID& transaction_id); @@ -164,7 +164,7 @@ public: BOOL regenerateLink(); public: - BOOL mIsComplete; + bool mIsComplete; LLTransactionID mTransactionID; }; -- 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/llaisapi.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 3bf9c78f564f0b6c4fd79163bd63c0a6c1fab7cb Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 28 Mar 2023 19:38:26 +0300 Subject: SL-18003 Improve dupplicate prevention Try getting lost and found --- indra/newview/llaisapi.cpp | 46 +++++++ indra/newview/llaisapi.h | 1 + indra/newview/llinventorymodel.cpp | 11 +- indra/newview/llinventorymodelbackgroundfetch.cpp | 147 +++++++++++++--------- indra/newview/llinventorymodelbackgroundfetch.h | 22 ++-- indra/newview/llviewerinventory.cpp | 28 +++-- indra/newview/llviewerinventory.h | 14 ++- 7 files changed, 183 insertions(+), 86 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 6a43c901e7..f869f1652b 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -445,6 +445,52 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec EnqueueAISCommand("FetchCategoryChildren", proc); } +// some folders can be requested by name, like +// animatn | bodypart | clothing | current | favorite | gesture | inbox | landmark | lsltext +// lstndfnd | my_otfts | notecard | object | outbox | root | snapshot | sound | texture | trash +void AISAPI::FetchCategoryChildren(const std::string &identifier, bool recursive, completion_t callback, S32 depth) +{ + std::string cap; + + cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + callback(LLUUID::null); + return; + } + std::string url = cap + std::string("/category/") + identifier + "/children"; + + if (recursive) + { + url += "?depth=*"; + } + else + { + url += "?depth=" + std::to_string(depth); + } + + 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"] = recursive ? S32_MAX : depth; + LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro, + _1, getFn, url, LLUUID::null, body, callback, FETCHCATEGORYCHILDREN)); + + EnqueueAISCommand("FetchCategoryChildren", proc); +} + /*static*/ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool recursive, completion_t callback, S32 depth) { diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index dd02951cd4..d083004195 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -57,6 +57,7 @@ public: static void UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback = completion_t()); static void FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callback = completion_t()); 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 CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t()); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index bfc7840708..9a874350bf 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -3453,8 +3453,8 @@ void LLInventoryModel::processUpdateCreateInventoryItem(LLMessageSystem* msg, vo gInventoryCallbacks.fire(callback_id, item_id); // todo: instead of unpacking message fully, - // grab only an item_id, then fetch via AIS - LLInventoryModelBackgroundFetch::instance().start(item_id, false); + // grab only an item_id, then fetch + LLInventoryModelBackgroundFetch::instance().scheduleItemFetch(item_id, true); } } @@ -3798,10 +3798,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 - - // Use AIS derectly to not reset folder's version - // Todo: May be LLInventoryModelBackgroundFetch needs a 'forced' option - AISAPI::FetchCategoryChildren((*cit)->getUUID(), AISAPI::INVENTORY); + LLInventoryModelBackgroundFetch::instance().scheduleFolderFetch((*cit)->getUUID(), true /*force, since it has changes*/); } for (item_array_t::iterator iit = items.begin(); iit != items.end(); ++iit) { @@ -3810,7 +3807,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().scheduleItemFetch((*iit)->getUUID()); + LLInventoryModelBackgroundFetch::instance().scheduleItemFetch((*iit)->getUUID(), true); } gInventory.notifyObservers(); diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 4cb4b9ee9c..a9357bfdb3 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -252,7 +252,7 @@ BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, bool recursive, bool is_category) { - ERecursionType recursion_type = recursive ? RT_RECURSIVE : RT_NONE; + EFetchType recursion_type = recursive ? FT_RECURSIVE : FT_DEFAULT; if (is_category) { mFetchFolderQueue.push_front(FetchQueueInfo(id, recursion_type, is_category)); @@ -265,7 +265,7 @@ void LLInventoryModelBackgroundFetch::addRequestAtFront(const LLUUID & id, bool void LLInventoryModelBackgroundFetch::addRequestAtBack(const LLUUID & id, bool recursive, bool is_category) { - ERecursionType recursion_type = recursive ? RT_RECURSIVE : RT_NONE; + EFetchType recursion_type = recursive ? FT_RECURSIVE : FT_DEFAULT; if (is_category) { mFetchFolderQueue.push_back(FetchQueueInfo(id, recursion_type, is_category)); @@ -287,7 +287,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) mBackgroundFetchActive = true; mFolderFetchActive = true; - ERecursionType recursion_type = recursive ? RT_RECURSIVE : RT_NONE; + EFetchType recursion_type = recursive ? FT_RECURSIVE : FT_DEFAULT; if (id.isNull()) { if (! mRecursiveInventoryFetchStarted) @@ -298,7 +298,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(), RT_CONTENT)); + mFetchFolderQueue.push_front(FetchQueueInfo(gInventory.getRootFolderID(), FT_CONTENT_RECURSIVE)); } else { @@ -351,32 +351,45 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive) } } -void LLInventoryModelBackgroundFetch::scheduleItemFetch(const LLUUID& item_id) +void LLInventoryModelBackgroundFetch::scheduleFolderFetch(const LLUUID& cat_id, bool forced) { - if (mFetchItemQueue.empty() || mFetchItemQueue.front().mUUID != item_id) + if (AISAPI::isAvailable()) { - mBackgroundFetchActive = true; - - mFetchItemQueue.push_front(FetchQueueInfo(item_id, RT_NONE, false)); + 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) + { + // Specific folder requests go to front of queue. + mFetchFolderQueue.push_front(FetchQueueInfo(cat_id, forced ? FT_FORCED : FT_DEFAULT)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } -void LLInventoryModelBackgroundFetch::findLostItems() +void LLInventoryModelBackgroundFetch::scheduleItemFetch(const LLUUID& item_id, bool forced) { - if (AISAPI::isAvailable()) - { - LL_WARNS() << "Not implemented yet" << LL_ENDL; - } - else + if (mFetchItemQueue.empty() || mFetchItemQueue.front().mUUID != item_id) { mBackgroundFetchActive = true; - mFolderFetchActive = true; - mFetchFolderQueue.push_back(FetchQueueInfo(LLUUID::null, RT_RECURSIVE)); + + mFetchItemQueue.push_front(FetchQueueInfo(item_id, forced ? FT_FORCED : FT_DEFAULT, false)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } +void LLInventoryModelBackgroundFetch::findLostItems() +{ + mBackgroundFetchActive = true; + mFolderFetchActive = true; + mFetchFolderQueue.push_back(FetchQueueInfo(LLUUID::null, FT_RECURSIVE)); + gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); +} + void LLInventoryModelBackgroundFetch::setAllFoldersFetched() { if (mRecursiveInventoryFetchStarted && @@ -449,7 +462,10 @@ void ais_simple_folder_callback(const LLUUID& inv_id) { LLInventoryModelBackgroundFetch::instance().incrFetchFolderCount(-1); LLViewerInventoryCategory * cat(gInventory.getCategory(inv_id)); - if (cat) cat->setFetching(false); + if (cat) + { + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + } } void ais_simple_item_callback(const LLUUID& inv_id) @@ -457,24 +473,24 @@ void ais_simple_item_callback(const LLUUID& inv_id) LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } -void LLInventoryModelBackgroundFetch::onAISFodlerCalback(const LLUUID &request_id, const LLUUID &response_id, ERecursionType recursion) +void LLInventoryModelBackgroundFetch::onAISFodlerCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType recursion) { incrFetchFolderCount(-1); if (response_id.isNull()) // Failure { - if (recursion == RT_RECURSIVE) + if (recursion == FT_RECURSIVE) { // A full recursive request failed. // Try requesting folder and nested content separately mBackgroundFetchActive = true; mFolderFetchActive = true; - mFetchFolderQueue.push_front(FetchQueueInfo(request_id, RT_CONTENT)); + mFetchFolderQueue.push_front(FetchQueueInfo(request_id, FT_CONTENT_RECURSIVE)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); } } else { - if (recursion == RT_CONTENT) + if (recursion == FT_CONTENT_RECURSIVE) { // Got the folder, now recursively request content LLInventoryModel::cat_array_t * categories(NULL); @@ -484,7 +500,7 @@ void LLInventoryModelBackgroundFetch::onAISFodlerCalback(const LLUUID &request_i it != categories->end(); ++it) { - mFetchFolderQueue.push_front(FetchQueueInfo((*it)->getUUID(), RT_RECURSIVE)); + mFetchFolderQueue.push_front(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE)); } if (!mFetchFolderQueue.empty()) { @@ -499,7 +515,7 @@ void LLInventoryModelBackgroundFetch::onAISFodlerCalback(const LLUUID &request_i LLViewerInventoryCategory * cat(gInventory.getCategory(request_id)); if (cat) { - cat->setFetching(false); + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); } } @@ -561,12 +577,11 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc if (fetch_info.mIsCategory) { const LLUUID & cat_id(fetch_info.mUUID); - if (cat_id.isNull()) // Lost and found + if (cat_id.isNull()) { - 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); - incrFetchFolderCount(1);*/ + // Lost and found + AISAPI::FetchCategoryChildren("lstndfnd", true, ais_simple_folder_callback); + incrFetchFolderCount(1); } else { @@ -574,32 +589,42 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); if (cat) { - if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) + if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion() || fetch_info.mFetchType == FT_FORCED) { - if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) - { - AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::LIBRARY, fetch_info.mRecursive == RT_RECURSIVE, ais_simple_folder_callback); - } - else + LLViewerInventoryCategory::EFetchType target_state = + fetch_info.mFetchType >= FT_CONTENT_RECURSIVE + ? LLViewerInventoryCategory::FETCH_RECURSIVE + : LLViewerInventoryCategory::FETCH_NORMAL; + // start again if we did a non-recursive fetch before + if (cat->getFetching() < target_state) { - LLUUID cat_id = cat->getUUID(); - ERecursionType type = fetch_info.mRecursive; - AISAPI::FetchCategoryChildren( - cat_id, - AISAPI::INVENTORY, - type == RT_RECURSIVE, - [cat_id, type](const LLUUID &response_id) + + if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) { - LLInventoryModelBackgroundFetch::instance().onAISFodlerCalback(cat_id, response_id, type); - }); + AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::LIBRARY, fetch_info.mFetchType == FT_RECURSIVE, ais_simple_folder_callback); + } + else + { + LLUUID cat_id = cat->getUUID(); + EFetchType type = fetch_info.mFetchType; + AISAPI::FetchCategoryChildren( + cat_id, + AISAPI::INVENTORY, + type == FT_RECURSIVE, + [cat_id, type](const LLUUID &response_id) + { + LLInventoryModelBackgroundFetch::instance().onAISFodlerCalback(cat_id, response_id, type); + }); + } + incrFetchFolderCount(1); + + cat->setFetching(target_state); } - incrFetchFolderCount(1); - cat->setFetching(true); } else { // Already fetched, check if anything inside needs fetching - if (fetch_info.mRecursive) + if (fetch_info.mFetchType >= FT_CONTENT_RECURSIVE) { LLInventoryModel::cat_array_t * categories(NULL); LLInventoryModel::item_array_t * items(NULL); @@ -609,7 +634,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc ++it) { // not push_front to not cause an infinite loop - mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); + mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mFetchType)); } } } @@ -622,21 +647,25 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc if (itemp) { - if (itemp->getPermissions().getOwner() == gAgent.getID()) - { - AISAPI::FetchItem(fetch_info.mUUID, AISAPI::INVENTORY, ais_simple_item_callback); - } - else + if (!itemp->isFinished() || fetch_info.mFetchType == FT_FORCED) { - AISAPI::FetchItem(fetch_info.mUUID, AISAPI::LIBRARY, ais_simple_item_callback); + if (itemp->getPermissions().getOwner() == gAgent.getID()) + { + AISAPI::FetchItem(fetch_info.mUUID, AISAPI::INVENTORY, ais_simple_item_callback); + } + else + { + AISAPI::FetchItem(fetch_info.mUUID, AISAPI::LIBRARY, ais_simple_item_callback); + } + mFetchCount++; } } - else + else // We don't know it, assume incomplete { // Assume agent's inventory, library wouldn't have gotten here AISAPI::FetchItem(fetch_info.mUUID, AISAPI::INVENTORY, ais_simple_item_callback); + mFetchCount++; } - mFetchCount++; } } @@ -736,7 +765,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() else { // May already have this folder, but append child folders to list. - if (fetch_info.mRecursive) + if (fetch_info.mFetchType >= FT_CONTENT_RECURSIVE) { LLInventoryModel::cat_array_t * categories(NULL); LLInventoryModel::item_array_t * items(NULL); @@ -745,13 +774,13 @@ void LLInventoryModelBackgroundFetch::bulkFetch() it != categories->end(); ++it) { - mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); + mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mFetchType)); } } } } } - if (fetch_info.mRecursive) + if (fetch_info.mFetchType >= FT_CONTENT_RECURSIVE) { recursive_cats.push_back(cat_id); } diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 6a8b616a82..eae2ba6af8 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -47,10 +47,11 @@ class LLInventoryModelBackgroundFetch : public LLSingleton fetch_queue_t; - void onAISFodlerCalback(const LLUUID &request_id, const LLUUID &response_id, ERecursionType recursion); + void onAISFodlerCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType recursion); void bulkFetchViaAis(); void bulkFetchViaAis(const FetchQueueInfo& fetch_info); void bulkFetch(); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 6f62ba5409..8ec7719ade 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -561,7 +561,8 @@ LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& uuid, LLInventoryCategory(uuid, parent_uuid, pref, name), mOwnerID(owner_id), mVersion(LLViewerInventoryCategory::VERSION_UNKNOWN), - mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN) + mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN), + mFetching(FETCH_NONE) { mDescendentsRequested.reset(); } @@ -569,7 +570,8 @@ LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& uuid, LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& owner_id) : mOwnerID(owner_id), mVersion(LLViewerInventoryCategory::VERSION_UNKNOWN), - mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN) + mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN), + mFetching(FETCH_NONE) { mDescendentsRequested.reset(); } @@ -670,21 +672,33 @@ bool LLViewerInventoryCategory::fetch() return false; } -void LLViewerInventoryCategory::setFetching(bool fetching) +LLViewerInventoryCategory::EFetchType LLViewerInventoryCategory::getFetching() { - if (fetching) + // if timer hasn't expired, request was scheduled, but not in progress + // if mFetching request was actually started + if (mDescendentsRequested.hasExpired()) { - if ((VERSION_UNKNOWN == getVersion()) - && mDescendentsRequested.hasExpired()) + mFetching = FETCH_NONE; + } + return mFetching; +} + +void LLViewerInventoryCategory::setFetching(LLViewerInventoryCategory::EFetchType fetching) +{ + if (fetching > mFetching) // allow a switch from normal to recursive + { + if (mDescendentsRequested.hasExpired() || (mFetching == FETCH_NONE)) { const F32 FETCH_TIMER_EXPIRY = 10.0f; mDescendentsRequested.reset(); mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY); } + mFetching = fetching; } - else + else if (fetching = FETCH_NONE) { mDescendentsRequested.stop(); + mFetching = fetching; } } diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 2ae2cebe5c..95a4c84999 100644 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -209,10 +209,17 @@ public: S32 getVersion() const; void setVersion(S32 version); - // Returns true if a fetch was issued. + // Returns true if a fetch was issued (not nessesary in progress). bool fetch(); - // Returns true if a fetch was issued. - void setFetching(bool); + + typedef enum { + FETCH_NONE = 0, + FETCH_NORMAL, + FETCH_RECURSIVE, + } EFetchType; + EFetchType getFetching(); + // marks as fetch being in progress or as done + void setFetching(EFetchType); // used to help make caching more robust - for example, if // someone is getting 4 packets but logs out after 3. the viewer @@ -242,6 +249,7 @@ protected: LLUUID mOwnerID; S32 mVersion; S32 mDescendentCount; + EFetchType mFetching; LLFrameTimer mDescendentsRequested; }; -- cgit v1.3 From 69e3b5fb4014ef900b129ebde49325f1b074e773 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 11 Apr 2023 01:33:24 +0300 Subject: SL-19533 Orphans plus additional logging --- indra/newview/llaisapi.cpp | 88 +++++++++++++++++++++-- indra/newview/llaisapi.h | 3 + indra/newview/llinventorymodelbackgroundfetch.cpp | 17 +++-- 3 files changed, 100 insertions(+), 8 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index f869f1652b..1efba0db7a 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -534,6 +534,35 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r EnqueueAISCommand("FetchCategoryCategories", proc); } +/*static*/ +void AISAPI::FetchOrphans(completion_t callback) +{ + std::string cap = getInvCap(); + if (cap.empty()) + { + LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + return; + } + std::string url = cap + std::string("/orphans"); + + 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 , FETCHORPHANS)); + + EnqueueAISCommand("FetchOrphans" , proc); +} + /*static*/ void AISAPI::EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc) { @@ -595,7 +624,8 @@ void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, CO } bool is_fetch = (type == FETCHITEM) || (type == FETCHCATEGORYCHILDREN) - || (type == FETCHCATEGORYCATEGORIES); + || (type == FETCHCATEGORYCATEGORIES) + || (type == FETCHORPHANS); // parse update llsd into stuff to do or parse received items. S32 depth = 0; if (is_fetch && request_body.has("depth")) @@ -620,9 +650,30 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; - LLSD result = invoke(httpAdapter, httpRequest, url, body, httpOptions, httpHeaders); - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + LLSD result; + LLSD httpResults; + LLCore::HttpStatus status; + + if (debugLoggingEnabled("AIS3")) + { + LLTimer ais_timer; + ais_timer.start(); + result = invoke(httpAdapter , httpRequest , url , body , httpOptions , httpHeaders); + httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + F32MillisecondsImplicit elapsed_time = ais_timer.getElapsedTimeF32(); + LL_DEBUGS("AIS3") << "Request type: " << (S32)type + << " \nRequest url: " << url + << " \nRequest target: " << targetId + << " \nElapsed time: " << elapsed_time + << " \nstatus: " << status.toULong() << LL_ENDL; + } + else + { + result = invoke(httpAdapter , httpRequest , url , body , httpOptions , httpHeaders); + httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + } if (!status || !result.isMap()) { @@ -756,6 +807,7 @@ void AISUpdate::clearParseResults() mCatDescendentsKnown.clear(); mCatVersionsUpdated.clear(); mItemsCreated.clear(); + mItemsLost.clear(); mItemsUpdated.clear(); mCategoriesCreated.clear(); mCategoriesUpdated.clear(); @@ -891,6 +943,11 @@ void AISUpdate::parseItem(const LLSD& item_map) mItemsCreated[item_id] = new_item; mCatDescendentDeltas[new_item->getParentUUID()]; new_item->setComplete(true); + + if (new_item->getParentUUID().isNull()) + { + mItemsLost[item_id] = new_item; + } } else if (curr_item) { @@ -940,6 +997,11 @@ void AISUpdate::parseLink(const LLSD& link_map) mItemsCreated[item_id] = new_link; mCatDescendentDeltas[parent_id]; new_link->setComplete(true); + + if (new_link->getParentUUID().isNull()) + { + mItemsLost[item_id] = new_link; + } } else if (curr_link) { @@ -1299,6 +1361,24 @@ void AISUpdate::doUpdate() } } + // LOST ITEMS + if (!mItemsLost.empty()) + { + LL_INFOS("Inventory") << "Received " << (S32)mItemsLost.size() << " items without a parent" << LL_ENDL; + const LLUUID lost_uuid(gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); + if (lost_uuid.notNull()) + { + for (deferred_item_map_t::const_iterator lost_it = mItemsLost.begin(); + lost_it != mItemsLost.end(); ++lost_it) + { + LLPointer new_item = lost_it->second; + + new_item->setParent(lost_uuid); + new_item->updateParentOnServer(FALSE); + } + } + } + // CREATE ITEMS for (deferred_item_map_t::const_iterator create_it = mItemsCreated.begin(); create_it != mItemsCreated.end(); ++create_it) diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index d083004195..4e1c6e5a7d 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -59,6 +59,7 @@ 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 FetchOrphans(completion_t callback = completion_t() ); static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t()); private: @@ -75,6 +76,7 @@ private: FETCHITEM, FETCHCATEGORYCHILDREN, FETCHCATEGORYCATEGORIES, + FETCHORPHANS, } COMMAND_TYPE; static const std::string INVENTORY_CAP_NAME; @@ -127,6 +129,7 @@ private: typedef std::map > deferred_item_map_t; deferred_item_map_t mItemsCreated; + deferred_item_map_t mItemsLost; deferred_item_map_t mItemsUpdated; typedef std::map > deferred_category_map_t; deferred_category_map_t mCategoriesCreated; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index e988f949e2..35b9442966 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -461,10 +461,13 @@ void LLInventoryModelBackgroundFetch::incrFetchFolderCount(S32 fetching) void ais_simple_folder_callback(const LLUUID& inv_id) { LLInventoryModelBackgroundFetch::instance().incrFetchFolderCount(-1); - LLViewerInventoryCategory * cat(gInventory.getCategory(inv_id)); - if (cat) + if (inv_id.notNull()) // null normally means a failure, but is an expected response for orphans { - cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + LLViewerInventoryCategory* cat(gInventory.getCategory(inv_id)); + if (cat) + { + cat->setFetching(LLViewerInventoryCategory::FETCH_NONE); + } } } @@ -580,6 +583,11 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() mFetchItemQueue.pop_front(); curent_time = LLTimer::getTotalSeconds(); } + + LL_DEBUGS(LOG_INV , "AIS3") << "Total active fetches: " << mFetchCount + << ", scheduled fodler fetches: " << (S32)mFetchFolderQueue.size() + << ", scheduled item fetches: " << (S32)mFetchItemQueue.size() + << LL_ENDL; if (isFolderFetchProcessingComplete() && mFolderFetchActive) { @@ -600,7 +608,8 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc if (cat_id.isNull()) { // Lost and found - AISAPI::FetchCategoryChildren("lstndfnd", true, ais_simple_folder_callback); + // Should it actually be recursive? + AISAPI::FetchOrphans(ais_simple_folder_callback); incrFetchFolderCount(1); } else -- cgit v1.3 From 5e59ab0ab77d91f9d855bd5a3fc0e5c691220f01 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 11 Apr 2023 23:12:32 +0300 Subject: SL-19533 Further logging improvements --- indra/newview/llaisapi.cpp | 65 +++++++++++++++++++++-- indra/newview/llinventorymodelbackgroundfetch.cpp | 26 ++++++--- indra/newview/llinventorymodelbackgroundfetch.h | 1 + indra/newview/llviewerinventory.cpp | 2 +- 4 files changed, 82 insertions(+), 12 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 1efba0db7a..92589540f1 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -29,6 +29,7 @@ #include "llaisapi.h" #include "llagent.h" +#include "llappviewer.h" #include "llcallbacklist.h" #include "llinventorymodel.h" #include "llsdutil.h" @@ -95,7 +96,10 @@ void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, c if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; - callback(LLUUID::null); + if (callback) + { + callback(LLUUID::null); + } return; } @@ -138,6 +142,10 @@ void AISAPI::SlamFolder(const LLUUID& folderId, const LLSD& newInventory, comple if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } return; } @@ -173,6 +181,10 @@ void AISAPI::RemoveCategory(const LLUUID &categoryId, completion_t callback) if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } return; } @@ -206,6 +218,10 @@ void AISAPI::RemoveItem(const LLUUID &itemId, completion_t callback) if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } return; } @@ -238,6 +254,10 @@ void AISAPI::CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, b if (cap.empty()) { LL_WARNS("Inventory") << "Library cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } return; } @@ -282,6 +302,10 @@ void AISAPI::PurgeDescendents(const LLUUID &categoryId, completion_t callback) if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } return; } @@ -316,6 +340,10 @@ void AISAPI::UpdateCategory(const LLUUID &categoryId, const LLSD &updates, compl 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/") + categoryId.asString(); @@ -348,6 +376,10 @@ void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } return; } std::string url = cap + std::string("/item/") + itemId.asString(); @@ -379,6 +411,10 @@ void AISAPI::FetchItem(const LLUUID &itemId, ITEM_TYPE type, completion_t callba if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } return; } std::string url = cap + std::string("/item/") + itemId.asString(); @@ -410,7 +446,10 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; - callback(LLUUID::null); + if (callback) + { + callback(LLUUID::null); + } return; } std::string url = cap + std::string("/category/") + catId.asString() + "/children"; @@ -456,7 +495,10 @@ void AISAPI::FetchCategoryChildren(const std::string &identifier, bool recursive if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; - callback(LLUUID::null); + if (callback) + { + callback(LLUUID::null); + } return; } std::string url = cap + std::string("/category/") + identifier + "/children"; @@ -500,6 +542,10 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r 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() + "/categories"; @@ -541,6 +587,10 @@ void AISAPI::FetchOrphans(completion_t callback) if (cap.empty()) { LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL; + if (callback) + { + callback(LLUUID::null); + } return; } std::string url = cap + std::string("/orphans"); @@ -642,6 +692,15 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht invokationFn_t invoke, std::string url, LLUUID targetId, LLSD body, completion_t callback, COMMAND_TYPE type) { + if (gDisconnected) + { + if (callback) + { + callback(LLUUID::null); + } + return; + } + LLCore::HttpOptions::ptr_t httpOptions(new LLCore::HttpOptions); LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); LLCore::HttpHeaders::ptr_t httpHeaders; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 0099e81b8f..955f152195 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -190,6 +190,7 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch(): mBackgroundFetchActive(false), mFolderFetchActive(false), mFetchCount(0), + mLastFetchCount(0), mFetchFolderCount(0), mAllRecursiveFoldersFetched(false), mRecursiveInventoryFetchStarted(false), @@ -424,13 +425,13 @@ void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *) void LLInventoryModelBackgroundFetch::backgroundFetch() { - if (mBackgroundFetchActive && gAgent.getRegion() && gAgent.getRegion()->capabilitiesReceived()) + if (mBackgroundFetchActive) { if (AISAPI::isAvailable()) { bulkFetchViaAis(); } - else + else if (gAgent.getRegion() && gAgent.getRegion()->capabilitiesReceived()) { // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. bulkFetch(); @@ -460,6 +461,7 @@ void LLInventoryModelBackgroundFetch::incrFetchFolderCount(S32 fetching) void ais_simple_folder_callback(const LLUUID& inv_id) { + LL_DEBUGS("AIS3") << "Response for folder " << inv_id << LL_ENDL; LLInventoryModelBackgroundFetch::instance().incrFetchFolderCount(-1); if (inv_id.notNull()) // null normally means a failure, but is an expected response for orphans { @@ -473,6 +475,7 @@ void ais_simple_folder_callback(const LLUUID& inv_id) void ais_simple_item_callback(const LLUUID& inv_id) { + LL_DEBUGS("AIS3") << "Response for " << inv_id << LL_ENDL; LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } @@ -481,6 +484,7 @@ void LLInventoryModelBackgroundFetch::onAISFodlerCalback(const LLUUID &request_i incrFetchFolderCount(-1); if (response_id.isNull()) // Failure { + LL_DEBUGS("AIS3") << "Failure response for folder " << request_id << LL_ENDL; if (recursion == FT_RECURSIVE) { // A full recursive request failed. @@ -513,6 +517,7 @@ void LLInventoryModelBackgroundFetch::onAISFodlerCalback(const LLUUID &request_i } else { + LL_DEBUGS("AIS3") << "Got folder " << request_id << LL_ENDL; if (recursion == FT_CONTENT_RECURSIVE) { // Got the folder, now recursively request content @@ -567,6 +572,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() ? 0.006f // 6 ms : 1.f; const F64 end_time = curent_time + max_time; + S32 last_fetch_count = mFetchCount; while (!mFetchFolderQueue.empty() && mFetchCount < max_concurrent_fetches && curent_time < end_time) { @@ -589,10 +595,15 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() } } - LL_DEBUGS(LOG_INV , "AIS3") << "Total active fetches: " << mFetchCount - << ", scheduled fodler fetches: " << (S32)mFetchFolderQueue.size() - << ", scheduled item fetches: " << (S32)mFetchItemQueue.size() - << LL_ENDL; + if (last_fetch_count != mFetchCount // if anything was added + || mLastFetchCount != mFetchCount) // if anything was substracted + { + mLastFetchCount = mFetchCount; + LL_DEBUGS(LOG_INV , "AIS3") << "Total active fetches: " << last_fetch_count << "->" << mFetchCount + << ", scheduled fodler fetches: " << (S32)mFetchFolderQueue.size() + << ", scheduled item fetches: " << (S32)mFetchItemQueue.size() + << LL_ENDL; + } if (isFolderFetchProcessingComplete() && mFolderFetchActive) { @@ -619,7 +630,6 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc } else { - LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id)); if (cat) { @@ -630,9 +640,9 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc ? LLViewerInventoryCategory::FETCH_RECURSIVE : LLViewerInventoryCategory::FETCH_NORMAL; // start again if we did a non-recursive fetch before + // to get all children in a single request if (cat->getFetching() < target_state) { - if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) { AISAPI::FetchCategoryChildren(cat->getUUID(), AISAPI::LIBRARY, fetch_info.mFetchType == FT_RECURSIVE, ais_simple_folder_callback); diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index bd54c17c8d..6c2c3e96fa 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -120,6 +120,7 @@ private: bool mBackgroundFetchActive; bool mFolderFetchActive; S32 mFetchCount; + S32 mLastFetchCount; // for debug S32 mFetchFolderCount; LLFrameTimer mFetchTimer; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index c4edc3952b..cd51a00c52 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -689,7 +689,7 @@ void LLViewerInventoryCategory::setFetching(LLViewerInventoryCategory::EFetchTyp { if (mDescendentsRequested.hasExpired() || (mFetching == FETCH_NONE)) { - const F32 FETCH_TIMER_EXPIRY = 10.0f; + const F32 FETCH_TIMER_EXPIRY = 30.0f; mDescendentsRequested.reset(); mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY); } -- cgit v1.3 From 8b1a7085be07704a58e169d1133fc356a1745c74 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 12 Apr 2023 19:13:32 +0300 Subject: SL-19533 Logging tag change --- indra/newview/llaisapi.cpp | 13 ++++++------- indra/newview/llinventorymodelbackgroundfetch.cpp | 8 ++++---- 2 files changed, 10 insertions(+), 11 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 92589540f1..ef3305a69d 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -684,7 +684,7 @@ void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, CO } AISUpdate ais_update(update, is_fetch, depth); ais_update.doUpdate(); // execute the updates in the appropriate order. - LL_DEBUGS("Inventory") << "elapsed: " << timer.getElapsedTimeF32() << LL_ENDL; + LL_DEBUGS("Inventory", "AIS3") << "Elapsed processing: " << timer.getElapsedTimeF32() << LL_ENDL; } /*static*/ @@ -707,13 +707,11 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht httpOptions->setTimeout(180); - LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL; - LLSD result; LLSD httpResults; LLCore::HttpStatus status; - if (debugLoggingEnabled("AIS3")) + if (debugLoggingEnabled("Inventory")) { LLTimer ais_timer; ais_timer.start(); @@ -721,10 +719,11 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); F32MillisecondsImplicit elapsed_time = ais_timer.getElapsedTimeF32(); - LL_DEBUGS("AIS3") << "Request type: " << (S32)type + + LL_DEBUGS("Inventory") << "Request type: " << (S32)type << " \nRequest url: " << url << " \nRequest target: " << targetId - << " \nElapsed time: " << elapsed_time + << " \nElapsed time ince request: " << elapsed_time << " \nstatus: " << status.toULong() << LL_ENDL; } else @@ -785,7 +784,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; + LL_DEBUGS("Inventory", "AIS3") << "Result: " << result << LL_ENDL; onUpdateReceived("AISCommand", result, type, body); if (callback && !callback.empty()) diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 69f688d51e..f650cc383f 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -461,7 +461,7 @@ void LLInventoryModelBackgroundFetch::incrFetchFolderCount(S32 fetching) void ais_simple_item_callback(const LLUUID& inv_id) { - LL_DEBUGS("AIS3") << "Response for " << inv_id << LL_ENDL; + LL_DEBUGS(LOG_INV , "AIS3") << "Response for " << inv_id << LL_ENDL; LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); } @@ -488,7 +488,7 @@ void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_i if (response_id.isNull()) // Failure { - LL_DEBUGS("AIS3") << "Failure response for folder " << request_id << LL_ENDL; + LL_DEBUGS(LOG_INV , "AIS3") << "Failure response for folder " << request_id << LL_ENDL; if (recursion == FT_RECURSIVE) { // A full recursive request failed. @@ -521,7 +521,7 @@ void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_i } else { - LL_DEBUGS("AIS3") << "Got folder " << request_id << LL_ENDL; + LL_DEBUGS(LOG_INV , "AIS3") << "Got folder " << request_id << LL_ENDL; if (recursion == FT_CONTENT_RECURSIVE) { // Got the folder, now recursively request content @@ -611,7 +611,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() if (!mExpectedFolderIds.empty()) { // A folder seem to be stack fetching on QA account, print oldest folder out - LL_DEBUGS("AIS3") << "Oldest expected folder: "; + LL_DEBUGS(LOG_INV , "AIS3") << "Oldest expected folder: "; std::list::const_iterator iter = mExpectedFolderIds.begin(); LL_CONT << *iter; if ((*iter).notNull()) -- 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/llaisapi.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 6d0c07840c6eae4f854152da051c46b9320ea0dd Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 20 Apr 2023 20:04:11 +0300 Subject: SL-19533 Cap folder request depth --- indra/newview/llaisapi.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 7a87fc6c3d..d39bb57304 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -456,13 +456,17 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec if (recursive) { - url += "?depth=*"; + // can specify depth=*, but server side is going to cap requests + // and reject everything 'over the top',. + depth = 50; } else { - url += "?depth=" + std::to_string(depth); + depth = llmax(depth, 50); } + url += "?depth=" + std::to_string(depth); + invokationFn_t getFn = boost::bind( // Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload. static_cast @@ -477,7 +481,7 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec // get doesn't use body, can pass additional data LLSD body; - body["depth"] = recursive ? S32_MAX : depth; + body["depth"] = depth; LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro, _1, getFn, url, catId, body, callback, FETCHCATEGORYCHILDREN)); @@ -505,13 +509,17 @@ void AISAPI::FetchCategoryChildren(const std::string &identifier, bool recursive if (recursive) { - url += "?depth=*"; + // can specify depth=*, but server side is going to cap requests + // and reject everything 'over the top',. + depth = 50; } else { - url += "?depth=" + std::to_string(depth); + depth = llmax(depth, 50); } + url += "?depth=" + std::to_string(depth); + invokationFn_t getFn = boost::bind( // Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload. static_cast @@ -526,7 +534,7 @@ void AISAPI::FetchCategoryChildren(const std::string &identifier, bool recursive // get doesn't use body, can pass additional data LLSD body; - body["depth"] = recursive ? S32_MAX : depth; + body["depth"] = depth; LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro, _1, getFn, url, LLUUID::null, body, callback, FETCHCATEGORYCHILDREN)); @@ -552,13 +560,17 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r if (recursive) { - url += "?depth=*"; + // can specify depth=*, but server side is going to cap requests + // and reject everything 'over the top',. + depth = 50; } else { - url += "?depth=" + std::to_string(depth); + depth = llmax(depth, 50); } + url += "?depth=" + std::to_string(depth); + invokationFn_t getFn = boost::bind( // Humans ignore next line. It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload. static_cast -- cgit v1.3 From 9c2b0c709b3d1cf1a9243853a8df7089e2494057 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Apr 2023 01:34:35 +0300 Subject: SL-19533 Special COF handling --- indra/newview/llaisapi.cpp | 40 +++++++++++++++++++++++ indra/newview/llaisapi.h | 2 ++ indra/newview/llinventorymodelbackgroundfetch.cpp | 6 ++++ indra/newview/llinventorymodelbackgroundfetch.h | 1 + indra/newview/llstartup.cpp | 1 + 5 files changed, 50 insertions(+) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index d39bb57304..117a596cd2 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -592,6 +592,40 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r EnqueueAISCommand("FetchCategoryCategories", proc); } +/*static*/ +// Will get COF folder, links in it and items those links point to +void AISAPI::FetchCOF(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/current/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, FETCHCOF)); + + EnqueueAISCommand("FetchCOF", proc); +} + /*static*/ void AISAPI::FetchOrphans(completion_t callback) { @@ -687,6 +721,7 @@ void AISAPI::onUpdateReceived(const std::string& context, const LLSD& update, CO 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; @@ -1095,6 +1130,11 @@ void AISUpdate::parseLink(const LLSD& link_map) mCatDescendentDeltas[parent_id]++; new_link->setComplete(true); } + + if (link_map.has("_embedded")) + { + parseEmbedded(link_map["_embedded"], S32_MAX); + } } else { diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 4e1c6e5a7d..0ca0144d7b 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -59,6 +59,7 @@ 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 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()); @@ -76,6 +77,7 @@ private: FETCHITEM, FETCHCATEGORYCHILDREN, FETCHCATEGORYCATEGORIES, + FETCHCOF, FETCHORPHANS, } COMMAND_TYPE; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index bfb5ad9d12..f56532ff8c 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -391,6 +391,12 @@ 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 1881322e7a..db2d6db323 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -65,6 +65,7 @@ public: bool inventoryFetchInProgress() const; void findLostItems(); + void fetchCOF(); void incrFetchCount(S32 fetching); void incrFetchFolderCount(S32 fetching); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index a1f2753ada..161beaff19 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1898,6 +1898,7 @@ bool idle_startup() } LLInventoryModelBackgroundFetch::instance().start(); + LLInventoryModelBackgroundFetch::instance().fetchCOF(); gInventory.createCommonSystemCategories(); // It's debatable whether this flag is a good idea - sets all -- cgit v1.3 From c008d3e030ca4019e24de9a4831dc36727555fd2 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Apr 2023 12:25:15 +0300 Subject: SL-19533 Reduce inventory fetch stalls --- indra/newview/llaisapi.cpp | 11 ++++++++++- indra/newview/llaisapi.h | 6 ++++++ indra/newview/llinventoryfilter.cpp | 12 ++++++------ indra/newview/llinventorymodel.cpp | 3 ++- indra/newview/llinventorymodelbackgroundfetch.cpp | 9 +++++++-- 5 files changed, 31 insertions(+), 10 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 117a596cd2..7c293fcf63 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -771,7 +771,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht LL_DEBUGS("Inventory") << "Request type: " << (S32)type << " \nRequest target: " << targetId - << " \nElapsed time ince request: " << elapsed_time + << " \nElapsed time since request: " << elapsed_time << " \nstatus: " << status.toULong() << LL_ENDL; } else @@ -904,6 +904,8 @@ AISUpdate::AISUpdate(const LLSD& update, bool fetch, S32 depth) : mFetch(fetch) , mFetchDepth(depth) { + mTimer.setTimerExpirySec(debugLoggingEnabled("Inventory") ? EXPIRY_SECONDS_DEBUG : EXPIRY_SECONDS_LIVE); + mTimer.start(); parseUpdate(update); } @@ -1279,6 +1281,13 @@ void AISUpdate::parseDescendentCount(const LLUUID& category_id, const LLSD& embe void AISUpdate::parseEmbedded(const LLSD& embedded, S32 depth) { + if (mTimer.hasExpired()) + { + llcoro::suspend(); + LLCoros::checkStop(); + mTimer.setTimerExpirySec(debugLoggingEnabled("Inventory") ? EXPIRY_SECONDS_DEBUG : EXPIRY_SECONDS_LIVE); + } + if (embedded.has("links")) // _embedded in a category { parseEmbeddedLinks(embedded["links"]); diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 0ca0144d7b..1969448627 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -124,6 +124,11 @@ public: private: void clearParseResults(); + // Debug is very log-heavy, give it more time or it will take forever to process + // Todo: find a way to make throttle static isntead of per-request + const F32 EXPIRY_SECONDS_DEBUG = 1.f; + const F32 EXPIRY_SECONDS_LIVE = 0.01f; + typedef std::map uuid_int_map_t; uuid_int_map_t mCatDescendentDeltas; uuid_int_map_t mCatDescendentsKnown; @@ -144,6 +149,7 @@ private: uuid_list_t mCategoryIds; bool mFetch; S32 mFetchDepth; + LLTimer mTimer; }; #endif diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index d8e7b8ca67..5d6c3be168 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -195,11 +195,6 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const return true; } - if(!checkAgainstFilterThumbnails(folder_id)) - { - return false; - } - // when applying a filter, matching folders get their contents downloaded first // but make sure we are not interfering with pre-download if (isNotDefault() @@ -207,7 +202,7 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const && !LLInventoryModelBackgroundFetch::instance().inventoryFetchInProgress()) { LLViewerInventoryCategory* cat = gInventory.getCategory(folder_id); - if (!cat || (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)) + if ((!cat && folder_id.notNull()) || (cat && cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)) { // At the moment background fetch only cares about VERSION_UNKNOWN, // so do not check isCategoryComplete that compares descendant count @@ -215,6 +210,11 @@ bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const } } + if (!checkAgainstFilterThumbnails(folder_id)) + { + return false; + } + // Marketplace folder filtering const U32 filterTypes = mFilterOps.mFilterTypes; const U32 marketplace_filter = FILTERTYPE_MARKETPLACE_ACTIVE | FILTERTYPE_MARKETPLACE_INACTIVE | diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 873d3e1ccf..48539f4748 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -4681,7 +4681,6 @@ LLPointer LLInventoryModel::validate() const } else if (count_under_root > 1) { - LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL; validation_info->mDuplicateRequiredSystemFolders.insert(folder_type); if (!is_automatic && folder_type != LLFolderType::FT_SETTINGS) { @@ -4689,6 +4688,7 @@ LLPointer LLInventoryModel::validate() const // outfits, trash and other non-automatic folders. validation_info->mFatalSystemDuplicate++; fatal_errs++; + LL_WARNS("Inventory") << "Fatal inventory corruption: system folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL; } else { @@ -4697,6 +4697,7 @@ LLPointer LLInventoryModel::validate() const // Exception: FT_SETTINGS is not automatic, but only deserves a warning. validation_info->mWarnings["non_fatal_system_duplicate_under_root"]++; warning_count++; + LL_WARNS("Inventory") << "System folder type has excess copies under root, type " << ft << " count " << count_under_root << LL_ENDL; } } if (count_elsewhere > 0) diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 277ddb16ba..c5fb40409f 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -555,6 +555,8 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() } static LLCachedControl ais_pool(gSavedSettings, "PoolSizeAIS", 20); + // Don't have too many requests at once + // Reserve one request for actions outside of fetch (like renames) const U32 max_concurrent_fetches = llmax(1, ais_pool - 1); if (mFetchCount >= max_concurrent_fetches) @@ -562,6 +564,9 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() return; } + // Don't fire all requests at once + const U32 max_requests_this_run = llmin(mFetchCount + 5, max_concurrent_fetches); + // Don't loop for too long (in case of large, fully loaded inventory) F64 curent_time = LLTimer::getTotalSeconds(); const F64 max_time = LLStartUp::getStartupState() > STATE_WEARABLES_WAIT @@ -570,7 +575,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() const F64 end_time = curent_time + max_time; S32 last_fetch_count = mFetchCount; - while (!mFetchFolderQueue.empty() && mFetchCount < max_concurrent_fetches && curent_time < end_time) + while (!mFetchFolderQueue.empty() && mFetchCount < max_requests_this_run && curent_time < end_time) { const FetchQueueInfo & fetch_info(mFetchFolderQueue.front()); bulkFetchViaAis(fetch_info); @@ -581,7 +586,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() // 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) + while (!mFetchItemQueue.empty() && mFetchCount < max_requests_this_run && curent_time < end_time) { const FetchQueueInfo& fetch_info(mFetchItemQueue.front()); bulkFetchViaAis(fetch_info); -- cgit v1.3 From 8166a8d8d480d63c645ead7cd81b1b0afda225b4 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 25 Apr 2023 13:10:51 +0300 Subject: SL-19533 Fix a fetch blunder --- indra/newview/llaisapi.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 7c293fcf63..e16029f063 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -462,7 +462,7 @@ void AISAPI::FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type, bool rec } else { - depth = llmax(depth, 50); + depth = llmin(depth, 50); } url += "?depth=" + std::to_string(depth); @@ -515,7 +515,7 @@ void AISAPI::FetchCategoryChildren(const std::string &identifier, bool recursive } else { - depth = llmax(depth, 50); + depth = llmin(depth, 50); } url += "?depth=" + std::to_string(depth); @@ -566,7 +566,7 @@ void AISAPI::FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type, bool r } else { - depth = llmax(depth, 50); + depth = llmin(depth, 50); } url += "?depth=" + std::to_string(depth); -- cgit v1.3 From 0091fa0cbaba034da09d42d49f68c63f2cc7df14 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 26 Apr 2023 03:53:05 +0300 Subject: SL-19583 Uniform risizing for combination inventory view --- indra/newview/llaisapi.cpp | 21 ++-- indra/newview/llaisapi.h | 1 + indra/newview/llinventorygallery.h | 1 + indra/newview/llpanelmaininventory.cpp | 47 +++++++-- indra/newview/llpanelmaininventory.h | 3 +- .../skins/default/xui/en/panel_main_inventory.xml | 114 ++++++++------------- 6 files changed, 98 insertions(+), 89 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index e16029f063..6d13a06c54 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -924,6 +924,16 @@ void AISUpdate::clearParseResults() mCategoryIds.clear(); } +void AISUpdate::checkTimeout() +{ + if (mTimer.hasExpired()) + { + llcoro::suspend(); + LLCoros::checkStop(); + mTimer.setTimerExpirySec(debugLoggingEnabled("Inventory") ? EXPIRY_SECONDS_DEBUG : EXPIRY_SECONDS_LIVE); + } +} + void AISUpdate::parseUpdate(const LLSD& update) { clearParseResults(); @@ -1281,12 +1291,7 @@ void AISUpdate::parseDescendentCount(const LLUUID& category_id, const LLSD& embe void AISUpdate::parseEmbedded(const LLSD& embedded, S32 depth) { - if (mTimer.hasExpired()) - { - llcoro::suspend(); - LLCoros::checkStop(); - mTimer.setTimerExpirySec(debugLoggingEnabled("Inventory") ? EXPIRY_SECONDS_DEBUG : EXPIRY_SECONDS_LIVE); - } + checkTimeout(); if (embedded.has("links")) // _embedded in a category { @@ -1408,6 +1413,8 @@ void AISUpdate::parseEmbeddedCategories(const LLSD& categories, S32 depth) void AISUpdate::doUpdate() { + checkTimeout(); + // Do version/descendant accounting. for (std::map::const_iterator catit = mCatDescendentDeltas.begin(); catit != mCatDescendentDeltas.end(); ++catit) @@ -1571,6 +1578,8 @@ void AISUpdate::doUpdate() } } + checkTimeout(); + gInventory.notifyObservers(); } diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 1969448627..6afbbbd16e 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -123,6 +123,7 @@ public: void doUpdate(); private: void clearParseResults(); + void checkTimeout(); // Debug is very log-heavy, give it more time or it will take forever to process // Todo: find a way to make throttle static isntead of per-request diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index 1760535524..2cf038b7d8 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -128,6 +128,7 @@ public: bool hasDescendents(const LLUUID& cat_id); bool hasVisibleItems(); void handleModifiedFilter(); + LLScrollContainer* getScrollableContainer() { return mScrollPanel; } protected: diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 98099dd407..7cd6d7cb82 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -266,6 +266,8 @@ BOOL LLPanelMainInventory::postBuild() comb_gallery_filter.markDefault(); mCombinationGalleryPanel->setRootChangedCallback(boost::bind(&LLPanelMainInventory::onCombinationRootChanged, this, true)); + mCombinationScroller = getChild("combination_scroller"); + initListCommandsHandlers(); const std::string texture_upload_cost_str = std::to_string(LLAgentBenefitsMgr::current().getTextureUploadCost()); @@ -928,6 +930,7 @@ void LLPanelMainInventory::draw() mActivePanel->setSortOrder(order); mResortActivePanel = false; } + LLPanel::draw(); updateItemcountText(); updateCombinationVisibility(); @@ -1503,7 +1506,7 @@ void LLPanelMainInventory::toggleViewMode() getChild("default_inventory_panel")->setVisible(!mSingleFolderMode); getChild("single_folder_inventory")->setVisible(mSingleFolderMode && isListViewMode()); getChild("gallery_view_inventory")->setVisible(mSingleFolderMode && isGalleryViewMode()); - getChild("combination_view_inventory")->setVisible(mSingleFolderMode && isCombinationViewMode()); + getChild("combination_view_inventory")->setVisible(mSingleFolderMode && isCombinationViewMode()); getChild("nav_buttons")->setVisible(mSingleFolderMode); getChild("view_mode_btn")->setImageOverlay(mSingleFolderMode ? getString("default_mode_btn") : getString("single_folder_mode_btn")); @@ -2214,19 +2217,41 @@ void LLPanelMainInventory::updateCombinationVisibility() { if(mSingleFolderMode && isCombinationViewMode()) { - bool is_gallery_empty = !mCombinationGalleryPanel->hasVisibleItems(); - bool show_inv_pane = mCombinationInventoryPanel->hasVisibleItems() || is_gallery_empty || mForceShowInvLayout; - getChild("comb_gallery_layout")->setVisible(!is_gallery_empty); - getChild("comb_inventory_layout")->setVisible(show_inv_pane); - mCombinationInventoryPanel->getRootFolder()->setForceArrange(!show_inv_pane); - if(mCombinationInventoryPanel->hasVisibleItems()) + LLRect inner_rect = mCombinationInventoryPanel->getScrollableContainer()->getScrolledViewRect(); + LLRect inv_rect = mCombinationInventoryPanel->getRect(); + inv_rect.mBottom = 0; + inv_rect.mRight = inv_rect.mLeft + inner_rect.getWidth(); + if (!mCombinationGalleryPanel->hasVisibleItems() || mCombinationInventoryPanel->hasVisibleItems()) + { + inv_rect.mTop = inv_rect.mBottom + inner_rect.getHeight(); + } + else { - mForceShowInvLayout = false; + inv_rect.mTop = inv_rect.mBottom; } - if(is_gallery_empty) + + inner_rect = mCombinationGalleryPanel->getScrollableContainer()->getScrolledViewRect(); + LLRect galery_rect = mCombinationGalleryPanel->getRect(); + galery_rect.mBottom = inv_rect.mTop; + if (mCombinationGalleryPanel->hasVisibleItems()) { - mCombinationGalleryPanel->handleModifiedFilter(); + mCombinationGalleryPanel->setVisible(true); + galery_rect.mTop = galery_rect.mBottom + inner_rect.getHeight(); } + else + { + mCombinationGalleryPanel->setVisible(false); + galery_rect.mTop = galery_rect.mBottom; + } + + LLRect scroller_rect = mCombinationScroller->getRect(); + scroller_rect.mBottom = 0; + scroller_rect.mTop = scroller_rect.mBottom + inv_rect.getHeight() + galery_rect.getHeight(); + scroller_rect.mRight = scroller_rect.mLeft + llmax(inv_rect.getWidth(), galery_rect.getWidth()); + + mCombinationScroller->setRect(scroller_rect); + mCombinationGalleryPanel->handleReshape(galery_rect, false); + mCombinationInventoryPanel->handleReshape(inv_rect, false); getActivePanel()->getRootFolder(); } @@ -2293,7 +2318,7 @@ void LLPanelMainInventory::setViewMode(EViewModeType mode) getChild("single_folder_inventory")->setVisible(mSingleFolderMode && isListViewMode()); getChild("gallery_view_inventory")->setVisible(mSingleFolderMode && isGalleryViewMode()); - getChild("combination_view_inventory")->setVisible(mSingleFolderMode && isCombinationViewMode()); + getChild("combination_view_inventory")->setVisible(mSingleFolderMode && isCombinationViewMode()); if(isListViewMode()) { diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h index e5b9ba929d..8e7ad776b0 100644 --- a/indra/newview/llpanelmaininventory.h +++ b/indra/newview/llpanelmaininventory.h @@ -143,8 +143,6 @@ protected: static BOOL filtersVisible(void* user_data); void onClearSearch(); - static void onFoldersByName(void *user_data); - static BOOL checkFoldersByName(void *user_data); static BOOL incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward); void onFilterSelected(); @@ -196,6 +194,7 @@ private: LLInventorySingleFolderPanel* mCombinationInventoryPanel; LLInventoryGallery* mCombinationGalleryPanel; + LLView* mCombinationScroller; boost::signals2::connection mListViewRootUpdatedConnection; boost::signals2::connection mGalleryRootUpdatedConnection; diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 5bc0113367..f772c1fde2 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -327,7 +327,7 @@ follows="all" layout="topleft" /> - - - - + + + + + + + - - - - - - - - - + -- 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/llaisapi.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 7bb564496997e26a4c9770cb509955d0a22d1617 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 27 Apr 2023 20:23:13 +0300 Subject: SL-19533 Subset fetch fixes --- indra/newview/llaisapi.cpp | 2 ++ indra/newview/llinventorymodelbackgroundfetch.cpp | 28 ++++++++++++++++------- indra/newview/llinventorymodelbackgroundfetch.h | 2 +- 3 files changed, 23 insertions(+), 9 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index c17b246ef1..e63d77cea3 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -916,6 +916,8 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht case COPYLIBRARYCATEGORY: case FETCHCATEGORYCATEGORIES: case FETCHCATEGORYCHILDREN: + case FETCHCATEGORYSUBSET: + case FETCHCOF: if (result.has("category_id")) { id = result["category_id"]; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index b8fdfab98a..3a2120750b 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -731,10 +731,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc 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; + LLViewerInventoryCategory::EFetchType target_state = LLViewerInventoryCategory::FETCH_RECURSIVE; // 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; @@ -747,8 +744,6 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc 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; } @@ -759,6 +754,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc if (children.empty()) { // fetch marketplace alone + // Should it actually be fetched as FT_FOLDER_AND_CONTENT? children.push_back(child_cat->getUUID()); mExpectedFolderIds.push_back(child_cat->getUUID()); child_cat->setFetching(target_state); @@ -803,7 +799,23 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc AISAPI::FetchCategorySubset(cat_id, children, item_type, true, cb, 0); } - if (!content_done) + if (content_done) + { + // This will have a bit of overlap with onAISContentCalback, + // but something else might have dowloaded folders, so verify + // every child that is complete has it's children done as well + for (LLInventoryModel::cat_array_t::iterator it = categories->begin(); + it != categories->end(); + ++it) + { + LLViewerInventoryCategory* child_cat = (*it); + if (LLViewerInventoryCategory::VERSION_UNKNOWN != child_cat->getVersion()) + { + mFetchFolderQueue.push_back(FetchQueueInfo(child_cat->getUUID(), FT_RECURSIVE)); + } + } + } + else { // send it back to get the rest mFetchFolderQueue.push_back(FetchQueueInfo(cat_id, FT_CONTENT_RECURSIVE)); @@ -844,7 +856,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc else { // Already fetched, check if anything inside needs fetching - if (fetch_info.mFetchType >= FT_CONTENT_RECURSIVE) + if (fetch_info.mFetchType == FT_RECURSIVE) { LLInventoryModel::cat_array_t * categories(NULL); LLInventoryModel::item_array_t * items(NULL); diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index 1fd7426312..e7be265a3d 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -84,7 +84,7 @@ protected: FT_DEFAULT = 0, FT_FORCED, // request non-recursively even if already loaded FT_CONTENT_RECURSIVE, // request content recursively - FT_FOLDER_AND_CONTENT, // request content recursively + FT_FOLDER_AND_CONTENT, // request folder, then content recursively FT_RECURSIVE, // request everything recursively } EFetchType; struct FetchQueueInfo -- cgit v1.3 From 4bfcf182d7a961d8ebfe17b453e54cfac26347ce Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 28 Apr 2023 19:34:26 +0300 Subject: SL-19533 Fetch stall prevention #2 --- indra/newview/llaisapi.cpp | 15 +++++++++++++++ indra/newview/llaisapi.h | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index e63d77cea3..951860e39d 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -1550,6 +1550,7 @@ void AISUpdate::doUpdate() } // CREATE CATEGORIES + const S32 MAX_UPDATE_BACKLOG = 50; // stall prevention for (deferred_category_map_t::const_iterator create_it = mCategoriesCreated.begin(); create_it != mCategoriesCreated.end(); ++create_it) { @@ -1558,6 +1559,13 @@ void AISUpdate::doUpdate() gInventory.updateCategory(new_category, LLInventoryObserver::CREATE); LL_DEBUGS("Inventory") << "created category " << category_id << LL_ENDL; + + // fetching can receive massive amount of items and fodlers + if (gInventory.getChangedIDs().size() > MAX_UPDATE_BACKLOG) + { + gInventory.notifyObservers(); + checkTimeout(); + } } // UPDATE CATEGORIES @@ -1612,6 +1620,13 @@ void AISUpdate::doUpdate() // case this is create. LL_DEBUGS("Inventory") << "created item " << item_id << LL_ENDL; gInventory.updateItem(new_item, LLInventoryObserver::CREATE); + + // fetching can receive massive amount of items and fodlers + if (gInventory.getChangedIDs().size() > MAX_UPDATE_BACKLOG) + { + gInventory.notifyObservers(); + checkTimeout(); + } } // UPDATE ITEMS diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 691c5db592..6270a34081 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -130,7 +130,7 @@ private: // Debug is very log-heavy, give it more time or it will take forever to process // Todo: find a way to make throttle static isntead of per-request const F32 EXPIRY_SECONDS_DEBUG = 1.f; - const F32 EXPIRY_SECONDS_LIVE = 0.01f; + const F32 EXPIRY_SECONDS_LIVE = 0.008f; typedef std::map uuid_int_map_t; uuid_int_map_t mCatDescendentDeltas; -- cgit v1.3 From 03c263a1cdd88ec5967e751cba8640edf9896e51 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 28 Apr 2023 23:37:34 +0300 Subject: SL-19533 Fix 'fetching' state timeout --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/llaisapi.cpp | 3 ++- indra/newview/llaisapi.h | 1 + indra/newview/llinventorymodelbackgroundfetch.cpp | 6 ++++-- indra/newview/llviewerinventory.cpp | 11 +++++++++-- 5 files changed, 27 insertions(+), 5 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index a2a1b3f117..43d3f63a34 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -15283,6 +15283,17 @@ Value 1 + BatchSizeAIS3 + + Comment + Amount of folder ais packs into category subset request + Persist + 1 + Type + S32 + Value + 20 + PoolSizeAIS Comment diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 951860e39d..b09b8ec517 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -46,6 +46,7 @@ //========================================================================= const std::string AISAPI::INVENTORY_CAP_NAME("InventoryAPIv3"); const std::string AISAPI::LIBRARY_CAP_NAME("LibraryAPIv3"); +const S32 AISAPI::HTTP_TIMEOUT = 180; std::list AISAPI::sPostponedQuery; @@ -823,7 +824,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); LLCore::HttpHeaders::ptr_t httpHeaders; - httpOptions->setTimeout(180); + httpOptions->setTimeout(HTTP_TIMEOUT); LL_DEBUGS("Inventory") << "Request url: " << url << LL_ENDL; diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h index 6270a34081..973c82a847 100644 --- a/indra/newview/llaisapi.h +++ b/indra/newview/llaisapi.h @@ -38,6 +38,7 @@ class AISAPI { public: + static const S32 HTTP_TIMEOUT; typedef enum { INVENTORY, LIBRARY diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 5f7950df08..8f1012868f 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -729,10 +729,12 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc gInventory.getDirectDescendentsOf(cat_id, categories, items); LLViewerInventoryCategory::EFetchType target_state = LLViewerInventoryCategory::FETCH_RECURSIVE; - // technically limit is 'as many as you can put into url', but for now stop at 10 - const S32 batch_limit = 20; bool content_done = true; + // Top limit is 'as many as you can put into url' + static LLCachedControl ais_batch(gSavedSettings, "BatchSizeAIS3", 20); + S32 batch_limit = llclamp(ais_batch(), 1, 40); + for (LLInventoryModel::cat_array_t::iterator it = categories->begin(); it != categories->end(); ++it) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 96f0b500a0..80e4f5f6d5 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -690,9 +690,16 @@ void LLViewerInventoryCategory::setFetching(LLViewerInventoryCategory::EFetchTyp { if (mDescendentsRequested.hasExpired() || (mFetching == FETCH_NONE)) { - const F32 FETCH_TIMER_EXPIRY = 30.0f; mDescendentsRequested.reset(); - mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY); + if (AISAPI::isAvailable()) + { + mDescendentsRequested.setTimerExpirySec(AISAPI::HTTP_TIMEOUT); + } + else + { + const F32 FETCH_TIMER_EXPIRY = 30.0f; + mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY); + } } mFetching = fetching; } -- cgit v1.3 From d42f2a1887a1bc94a97c08bfe676731672ce53d3 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 30 May 2023 00:01:58 +0300 Subject: SL-17429 Message user when their inventory hits AIS3 limits --- indra/newview/llaisapi.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index b09b8ec517..fcee3a3e91 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -32,11 +32,12 @@ #include "llappviewer.h" #include "llcallbacklist.h" #include "llinventorymodel.h" +#include "llinventoryobserver.h" +#include "llnotificationsutil.h" #include "llsdutil.h" #include "llviewerregion.h" #include "llvoavatar.h" #include "llvoavatarself.h" -#include "llinventoryobserver.h" #include "llviewercontrol.h" ///---------------------------------------------------------------------------- @@ -893,11 +894,21 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht } } } - else if (status.getType() == 403) + else if (status == LLCore::HttpStatus(HTTP_FORBIDDEN) /*403*/) { if (type == FETCHCATEGORYCHILDREN) { - LL_DEBUGS("Inventory") << "Fetch failed, content is over imit" << LL_ENDL; + if (body.has("depth") && body["depth"].asInteger() == 0) + { + // Can't fetch a single folder with depth 0, folder is too big. + LLNotificationsUtil::add("InventoryLimitReachedAIS"); + LL_WARNS("Inventory") << "Fetch failed, content is over limit, url: " << url << LL_ENDL; + } + else + { + // Result was too big, but situation is recoverable by requesting with lower depth + LL_DEBUGS("Inventory") << "Fetch failed, content is over limit, url: " << url << LL_ENDL; + } } } LL_WARNS("Inventory") << "Inventory error: " << status.toString() << LL_ENDL; -- cgit v1.3 From 42e6c35ace5c54c17460815a19c82486d8b450ca Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Fri, 2 Jun 2023 23:03:52 +0300 Subject: SL-17429 Message user when their inventory hits AIS3 limits #2 --- indra/newview/llaisapi.cpp | 11 ++++++++++- indra/newview/skins/default/xui/en/notifications.xml | 8 ++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index fcee3a3e91..4ac2acf1d1 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -901,7 +901,16 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht if (body.has("depth") && body["depth"].asInteger() == 0) { // Can't fetch a single folder with depth 0, folder is too big. - LLNotificationsUtil::add("InventoryLimitReachedAIS"); + static bool first_call = true; + if (first_call) + { + first_call = false; + LLNotificationsUtil::add("InventoryLimitReachedAISAlert"); + } + else + { + LLNotificationsUtil::add("InventoryLimitReachedAIS"); + } LL_WARNS("Inventory") << "Fetch failed, content is over limit, url: " << url << LL_ENDL; } else diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 4c8d7fbd83..aa8e6176e1 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6440,6 +6440,14 @@ Your trash is overflowing. This may cause problems logging in. yestext="Check trash folder"/> + +Your inventory is experiencing issues. Please, contact support. + fail + + 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/llaisapi.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 05b5540fe70067180be6bb664752742b31a49eb7 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Tue, 1 Aug 2023 23:53:57 +0300 Subject: SL-20107 Detaching items from COF in gallery view didn't update COF --- indra/newview/llaisapi.cpp | 30 +++++++++++++++++++++--------- indra/newview/llinventorygallery.cpp | 3 +++ 2 files changed, 24 insertions(+), 9 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index f3799361db..f26549cc3d 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -1321,6 +1321,7 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) if (curr_cat && curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN + && curr_cat->getDescendentCount() != LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN && version > LLViewerInventoryCategory::VERSION_UNKNOWN && version < curr_cat->getVersion()) { @@ -1429,15 +1430,26 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) void AISUpdate::parseDescendentCount(const LLUUID& category_id, const LLSD& embedded) { - // 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(); - } + if (mType == AISAPI::FETCHCOF) + { + // contains only links + if (embedded.has("links")) + { + mCatDescendentsKnown[category_id] = embedded["links"].size(); + } + } + else + { + // 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(); + } + } } void AISUpdate::parseEmbedded(const LLSD& embedded, S32 depth) diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 87dba5f100..0801b71e34 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2376,6 +2376,9 @@ void LLInventoryGalleryItem::setSelected(bool value) BOOL LLInventoryGalleryItem::handleMouseDown(S32 x, S32 y, MASK mask) { + // call changeItemSelection directly, before setFocus + // to avoid autoscroll from LLInventoryGallery::onFocusReceived() + mGallery->changeItemSelection(mUUID, false); setFocus(TRUE); mGallery->claimEditHandler(); -- cgit v1.3 From dd699f84c92020868656a2ad8086a73372e5a19d Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 5 Aug 2023 02:05:11 +0300 Subject: SL-20120 Do not account for deltas when fetching Is supposed to set version and descendant info in parseCategory --- indra/newview/llaisapi.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index f26549cc3d..34c6a1e8ab 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -1210,7 +1210,6 @@ void AISUpdate::parseItem(const LLSD& item_map) if (mFetch) { mItemsCreated[item_id] = new_item; - mCatDescendentDeltas[new_item->getParentUUID()]; new_item->setComplete(true); if (new_item->getParentUUID().isNull()) @@ -1264,7 +1263,6 @@ void AISUpdate::parseLink(const LLSD& link_map, S32 depth) new_link->setSaleInfo(default_sale_info); //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); if (new_link->getParentUUID().isNull()) @@ -1381,7 +1379,6 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) new_cat->setDescendentCount(descendent_count); } mCategoriesCreated[category_id] = new_cat; - mCatDescendentDeltas[new_cat->getParentUUID()]; } else if (curr_cat) { -- cgit v1.3 From 201cd961055d532d77e06f7d4c14fc082ef84a04 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sat, 5 Aug 2023 17:28:43 +0300 Subject: SL-20120 Fix folders with unknown content being assigned a version --- indra/newview/llaisapi.cpp | 65 ++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 25 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 34c6a1e8ab..07c6afc635 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -706,6 +706,10 @@ void AISAPI::FetchCOF(completion_t callback) LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro, _1, getFn, url, LLUUID::null, LLSD(), callback, FETCHCOF)); + LLSD body; + // Only cof folder will be full, but cof can contain an outfit + // link with embedded outfit folder for request to parse + body["depth"] = 0; EnqueueAISCommand("FetchCOF", proc); } @@ -1359,17 +1363,6 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) { if (mFetch) { - // set version only if previous one was already known - // or if we are sure this update has full data and embeded items (depth 0+) - // since bulk fetch uses this to decide what still needs fetching - if (version > LLViewerInventoryCategory::VERSION_UNKNOWN - && (depth >= 0 || (curr_cat && curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN))) - { - // Set version/descendents for newly fetched categories. - LL_DEBUGS("Inventory") << "Setting version to " << version - << " for category " << category_id << LL_ENDL; - new_cat->setVersion(version); - } uuid_int_map_t::const_iterator lookup_it = mCatDescendentsKnown.find(category_id); if (mCatDescendentsKnown.end() != lookup_it) { @@ -1377,6 +1370,26 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) LL_DEBUGS("Inventory") << "Setting descendents count to " << descendent_count << " for category " << category_id << LL_ENDL; new_cat->setDescendentCount(descendent_count); + + // 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))) + { + LL_DEBUGS("Inventory") << "Setting version to " << version + << " for category " << category_id << LL_ENDL; + new_cat->setVersion(version); + } + } + else if (curr_cat + && curr_cat->getVersion() > LLViewerInventoryCategory::VERSION_UNKNOWN + && version > curr_cat->getVersion()) + { + // Potentially should new_cat->setVersion(unknown) here, + // but might be waiting for a callback that would increment + LL_DEBUGS("Inventory") << "Category " << category_id + << " is stale. Known version: " << curr_cat->getVersion() + << " server version: " << version << LL_ENDL; } mCategoriesCreated[category_id] = new_cat; } @@ -1393,20 +1406,22 @@ void AISUpdate::parseCategory(const LLSD& category_map, S32 depth) else { // Set version/descendents for newly created categories. - if (category_map.has("version")) - { - S32 version = category_map["version"].asInteger(); - LL_DEBUGS("Inventory") << "Setting version to " << version - << " for new category " << category_id << LL_ENDL; - new_cat->setVersion(version); - } - uuid_int_map_t::const_iterator lookup_it = mCatDescendentsKnown.find(category_id); - if (mCatDescendentsKnown.end() != lookup_it) - { - S32 descendent_count = lookup_it->second; - LL_DEBUGS("Inventory") << "Setting descendents count to " << descendent_count - << " for new category " << category_id << LL_ENDL; - new_cat->setDescendentCount(descendent_count); + uuid_int_map_t::const_iterator lookup_it = mCatDescendentsKnown.find(category_id); + if (mCatDescendentsKnown.end() != lookup_it) + { + S32 descendent_count = lookup_it->second; + LL_DEBUGS("Inventory") << "Setting descendents count to " << descendent_count + << " for new category " << category_id << LL_ENDL; + new_cat->setDescendentCount(descendent_count); + + // Don't set version unles correct children count is present + if (category_map.has("version")) + { + S32 version = category_map["version"].asInteger(); + LL_DEBUGS("Inventory") << "Setting version to " << version + << " for new category " << category_id << LL_ENDL; + new_cat->setVersion(version); + } } mCategoriesCreated[category_id] = new_cat; mCatDescendentDeltas[new_cat->getParentUUID()]++; -- cgit v1.3 From cd8fcec5fefd607957ef2560fbe92241795c091b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Sun, 6 Aug 2023 15:22:38 +0300 Subject: SL-20120 Fix ais depth 'body' being misplaced. --- indra/newview/llaisapi.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 07c6afc635..0f58908251 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -703,13 +703,13 @@ void AISAPI::FetchCOF(completion_t callback) // _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, FETCHCOF)); - LLSD body; // Only cof folder will be full, but cof can contain an outfit // link with embedded outfit folder for request to parse body["depth"] = 0; + LLCoprocedureManager::CoProcedure_t proc(boost::bind(&AISAPI::InvokeAISCommandCoro, + _1, getFn, url, LLUUID::null, body, callback, FETCHCOF)); + EnqueueAISCommand("FetchCOF", proc); } -- cgit v1.3 From 8e1c5fee2b9c329eef9be503af740894aac27635 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 9 Aug 2023 12:52:17 +0300 Subject: SL-18629 Better item fetch error handling --- indra/newview/llaisapi.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 0f58908251..4546574955 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -986,6 +986,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht case FETCHITEM: if (result.has("item_id")) { + // Error message might contain an item_id!!! id = result["item_id"]; } if (result.has("linked_id")) @@ -1167,11 +1168,15 @@ void AISUpdate::parseMeta(const LLSD& update) void AISUpdate::parseContent(const LLSD& update) { - if (update.has("linked_id")) + // Errors from a fetch request might contain id without + // full item or folder. + // Todo: Depending on error we might want to do something, + // like removing a 404 item or refetching parent folder + if (update.has("linked_id") && update.has("parent_id")) { parseLink(update, mFetchDepth); } - else if (update.has("item_id")) + else if (update.has("item_id") && update.has("parent_id")) { parseItem(update); } @@ -1185,7 +1190,7 @@ void AISUpdate::parseContent(const LLSD& update) parseEmbedded(update["_embedded"], mFetchDepth - 1); } } - else if (update.has("category_id")) + else if (update.has("category_id") && update.has("parent_id")) { parseCategory(update, mFetchDepth); } -- cgit v1.3 From 74a1d2582c457aff738bf73c21e137015acfe6cb Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 17 Aug 2023 19:49:37 +0300 Subject: SL-20162 Better cof version logging And fixed some typos --- indra/newview/llaisapi.cpp | 4 ++-- indra/newview/llinventorymodelbackgroundfetch.cpp | 8 ++++---- indra/newview/llpanellandmarkinfo.cpp | 4 ++-- indra/newview/llpanellandmarkinfo.h | 2 +- indra/newview/llvoavatar.cpp | 9 ++++++++- 5 files changed, 17 insertions(+), 10 deletions(-) (limited to 'indra/newview/llaisapi.cpp') diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp index 4546574955..d8d30037c8 100644 --- a/indra/newview/llaisapi.cpp +++ b/indra/newview/llaisapi.cpp @@ -1646,7 +1646,7 @@ void AISUpdate::doUpdate() gInventory.updateCategory(new_category, LLInventoryObserver::CREATE); LL_DEBUGS("Inventory") << "created category " << category_id << LL_ENDL; - // fetching can receive massive amount of items and fodlers + // fetching can receive massive amount of items and folders if (gInventory.getChangedIDs().size() > MAX_UPDATE_BACKLOG) { gInventory.notifyObservers(); @@ -1707,7 +1707,7 @@ void AISUpdate::doUpdate() LL_DEBUGS("Inventory") << "created item " << item_id << LL_ENDL; gInventory.updateItem(new_item, LLInventoryObserver::CREATE); - // fetching can receive massive amount of items and fodlers + // fetching can receive massive amount of items and folders if (gInventory.getChangedIDs().size() > MAX_UPDATE_BACKLOG) { gInventory.notifyObservers(); diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 03205cfbda..44eccd955e 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -657,7 +657,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis() || mLastFetchCount != mFetchCount) // if anything was substracted { LL_DEBUGS(LOG_INV , "AIS3") << "Total active fetches: " << mLastFetchCount << "->" << last_fetch_count << "->" << mFetchCount - << ", scheduled fodler fetches: " << (S32)mFetchFolderQueue.size() + << ", scheduled folder fetches: " << (S32)mFetchFolderQueue.size() << ", scheduled item fetches: " << (S32)mFetchItemQueue.size() << LL_ENDL; mLastFetchCount = mFetchCount; @@ -1384,10 +1384,10 @@ void BGFolderHttpHandler::processFailure(LLCore::HttpStatus status, LLCore::Http while (iter != end) { folders.append(*iter); - LLUUID fodler_id = iter->get("folder_id").asUUID(); - if (std::find(mRecursiveCatUUIDs.begin(), mRecursiveCatUUIDs.end(), fodler_id) != mRecursiveCatUUIDs.end()) + LLUUID folder_id = iter->get("folder_id").asUUID(); + if (std::find(mRecursiveCatUUIDs.begin(), mRecursiveCatUUIDs.end(), folder_id) != mRecursiveCatUUIDs.end()) { - recursive_cats.push_back(fodler_id); + recursive_cats.push_back(folder_id); } if (folders.size() == (S32)(size / 2)) { diff --git a/indra/newview/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp index 834e664723..cc3c51dd83 100644 --- a/indra/newview/llpanellandmarkinfo.cpp +++ b/indra/newview/llpanellandmarkinfo.cpp @@ -111,9 +111,9 @@ void LLPanelLandmarkInfo::setInfoType(EInfoType type) } // Sets CREATE_LANDMARK infotype and creates landmark at desired folder -void LLPanelLandmarkInfo::setInfoAndCreateLandmark(const LLUUID& fodler_id) +void LLPanelLandmarkInfo::setInfoAndCreateLandmark(const LLUUID& folder_id) { - setInfoType(CREATE_LANDMARK, fodler_id); + setInfoType(CREATE_LANDMARK, folder_id); } void LLPanelLandmarkInfo::setInfoType(EInfoType type, const LLUUID &folder_id) diff --git a/indra/newview/llpanellandmarkinfo.h b/indra/newview/llpanellandmarkinfo.h index 46e2a1935b..8802ce066e 100644 --- a/indra/newview/llpanellandmarkinfo.h +++ b/indra/newview/llpanellandmarkinfo.h @@ -48,7 +48,7 @@ public: /*virtual*/ void setInfoType(EInfoType type); // Sets CREATE_LANDMARK infotype and creates landmark at desired folder - void setInfoAndCreateLandmark(const LLUUID& fodler_id); + void setInfoAndCreateLandmark(const LLUUID& folder_id); /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 305c489cc8..57a78181bd 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -9447,7 +9447,14 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) // RequestAgentUpdateAppearanceResponder::onRequestRequested() // assumes that cof version is only updated with server-bake // appearance messages. - LL_INFOS("Avatar") << "Processing appearance message version " << thisAppearanceVersion << LL_ENDL; + if (isSelf()) + { + LL_INFOS("Avatar") << "Processing appearance message version " << thisAppearanceVersion << LL_ENDL; + } + else + { + LL_INFOS("Avatar") << "Processing appearance message for " << getID() << ", version " << thisAppearanceVersion << LL_ENDL; + } // Note: // locally the COF is maintained via LLInventoryModel::accountForUpdate -- 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/llaisapi.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