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.2.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 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 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); + } } } -- cgit v1.2.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.2.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 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 180 insertions(+), 1 deletion(-) (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); -- cgit v1.2.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 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 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; } -- cgit v1.2.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 ++++++++++++++++++++------------------------- 1 file changed, 49 insertions(+), 64 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 -- cgit v1.2.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 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 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; -- cgit v1.2.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 +++++++++++++++++++++++++++++----------------- 1 file changed, 55 insertions(+), 32 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); } } } -- cgit v1.2.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 ----- 1 file changed, 5 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; -- cgit v1.2.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 ++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 32 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) { -- cgit v1.2.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 +++-- 1 file changed, 3 insertions(+), 2 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*/ -- cgit v1.2.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 + 1 file changed, 1 insertion(+) (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) { -- cgit v1.2.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 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (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 -- cgit v1.2.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 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (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) { -- cgit v1.2.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 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 4 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) -- cgit v1.2.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 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 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; -- cgit v1.2.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 ++++++------- 1 file changed, 6 insertions(+), 7 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()) -- cgit v1.2.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 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (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; -- cgit v1.2.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.2.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 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 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 { -- cgit v1.2.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 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (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"]); -- cgit v1.2.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.2.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 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 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(); } -- cgit v1.2.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 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 125 insertions(+), 33 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); } } } -- cgit v1.2.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 ++ 1 file changed, 2 insertions(+) (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"]; -- cgit v1.2.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 +++++++++++++++ 1 file changed, 15 insertions(+) (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 -- cgit v1.2.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/llaisapi.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/newview/llaisapi.cpp') 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; -- cgit v1.2.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.2.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 ++++++++++- 1 file changed, 10 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 -- cgit v1.2.3 From 3058e6e6fd66ad4abb91fa5354ee11f6b7843a02 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Wed, 19 Jul 2023 21:15:52 +0300 Subject: SL-20015 wait for the outfit items to load before wearing it --- indra/newview/llaisapi.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (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; -- cgit v1.2.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 +++++++++++++++++++++--------- 1 file changed, 21 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) -- cgit v1.2.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.2.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.2.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.2.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.2.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 ++-- 1 file changed, 2 insertions(+), 2 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(); -- cgit v1.2.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 +++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 28 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(); } } -- cgit v1.2.3