summaryrefslogtreecommitdiff
path: root/indra/newview/llaisapi.cpp
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2023-04-27 01:30:57 +0300
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2023-04-27 01:30:57 +0300
commit697d3be3c9906a6d578a961710fc43816b6adeae (patch)
tree22e65ad7410080d8307cfe42cddd21fd314b62c3 /indra/newview/llaisapi.cpp
parent0091fa0cbaba034da09d42d49f68c63f2cc7df14 (diff)
SL-19533 Implement subset variant of children request
Diffstat (limited to 'indra/newview/llaisapi.cpp')
-rw-r--r--indra/newview/llaisapi.cpp158
1 files changed, 125 insertions, 33 deletions
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::ais_query_item_t> 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<LLSD(LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string&, LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+ //----
+ // _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<LLViewerInventoryItem> 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);
}
}
}