SL-19533 Implement subset variant of children request
parent
0091fa0cba
commit
697d3be3c9
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,11 +59,11 @@ public:
|
|||
static void FetchCategoryChildren(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
|
||||
static void FetchCategoryChildren(const std::string &identifier, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
|
||||
static void FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
|
||||
static void FetchCategorySubset(const LLUUID& catId, const uuid_vec_t specificChildren, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
|
||||
static void FetchCOF(completion_t callback = completion_t());
|
||||
static void FetchOrphans(completion_t callback = completion_t() );
|
||||
static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t());
|
||||
|
||||
private:
|
||||
typedef enum {
|
||||
COPYINVENTORY,
|
||||
SLAMFOLDER,
|
||||
|
|
@ -77,10 +77,12 @@ private:
|
|||
FETCHITEM,
|
||||
FETCHCATEGORYCHILDREN,
|
||||
FETCHCATEGORYCATEGORIES,
|
||||
FETCHCATEGORYSUBSET,
|
||||
FETCHCOF,
|
||||
FETCHORPHANS,
|
||||
} COMMAND_TYPE;
|
||||
|
||||
private:
|
||||
static const std::string INVENTORY_CAP_NAME;
|
||||
static const std::string LIBRARY_CAP_NAME;
|
||||
|
||||
|
|
@ -89,7 +91,7 @@ private:
|
|||
|
||||
static void EnqueueAISCommand(const std::string &procName, LLCoprocedureManager::CoProcedure_t proc);
|
||||
static void onIdle(void *userdata); // launches postponed AIS commands
|
||||
static void onUpdateReceived(const std::string& context, const LLSD& update, COMMAND_TYPE type, const LLSD& request_body);
|
||||
static void onUpdateReceived(const LLSD& update, COMMAND_TYPE type, const LLSD& request_body);
|
||||
|
||||
static std::string getInvCap();
|
||||
static std::string getLibCap();
|
||||
|
|
@ -105,17 +107,17 @@ private:
|
|||
class AISUpdate
|
||||
{
|
||||
public:
|
||||
AISUpdate(const LLSD& update, bool fetch, S32 depth);
|
||||
AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD& request_body);
|
||||
void parseUpdate(const LLSD& update);
|
||||
void parseMeta(const LLSD& update);
|
||||
void parseContent(const LLSD& update);
|
||||
void parseUUIDArray(const LLSD& content, const std::string& name, uuid_list_t& ids);
|
||||
void parseLink(const LLSD& link_map);
|
||||
void parseLink(const LLSD& link_map, S32 depth);
|
||||
void parseItem(const LLSD& link_map);
|
||||
void parseCategory(const LLSD& link_map, S32 depth);
|
||||
void parseDescendentCount(const LLUUID& category_id, const LLSD& embedded);
|
||||
void parseEmbedded(const LLSD& embedded, S32 depth);
|
||||
void parseEmbeddedLinks(const LLSD& links);
|
||||
void parseEmbeddedLinks(const LLSD& links, S32 depth);
|
||||
void parseEmbeddedItems(const LLSD& items);
|
||||
void parseEmbeddedCategories(const LLSD& categories, S32 depth);
|
||||
void parseEmbeddedItem(const LLSD& item);
|
||||
|
|
@ -151,6 +153,7 @@ private:
|
|||
bool mFetch;
|
||||
S32 mFetchDepth;
|
||||
LLTimer mTimer;
|
||||
AISAPI::COMMAND_TYPE mType;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -4568,7 +4568,18 @@ void callAfterCOFFetch(nullary_func_t cb)
|
|||
if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN && AISAPI::isAvailable())
|
||||
{
|
||||
// Assume that we have no relevant cache. Fetch cof, and items cof's links point to.
|
||||
AISAPI::FetchCOF([cb](const LLUUID& id) { cb(); });
|
||||
AISAPI::FetchCOF([cb](const LLUUID& id)
|
||||
{
|
||||
cb();
|
||||
LLUUID cat_id = LLAppearanceMgr::instance().getCOF();
|
||||
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
|
||||
if (cat)
|
||||
{
|
||||
cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
|
||||
}
|
||||
});
|
||||
// Mark it so that background fetch won't request it if it didn't already
|
||||
cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -299,7 +299,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, bool recursive)
|
|||
// Not only root folder can be massive, but
|
||||
// most system folders will be requested independently
|
||||
// so request root folder and content separately
|
||||
mFetchFolderQueue.push_front(FetchQueueInfo(gInventory.getRootFolderID(), FT_CONTENT_RECURSIVE));
|
||||
mFetchFolderQueue.push_front(FetchQueueInfo(gInventory.getRootFolderID(), FT_FOLDER_AND_CONTENT));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -455,10 +455,67 @@ void ais_simple_item_callback(const LLUUID& inv_id)
|
|||
LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1);
|
||||
}
|
||||
|
||||
void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType recursion)
|
||||
void LLInventoryModelBackgroundFetch::onAISContentCalback(
|
||||
const LLUUID& request_id,
|
||||
const uuid_vec_t& content_ids,
|
||||
const LLUUID& response_id,
|
||||
EFetchType fetch_type)
|
||||
{
|
||||
// Don't push_front on failure - there is a chance it was fired from inside bulkFetchViaAis
|
||||
incrFetchFolderCount(-1);
|
||||
std::list<LLUUID>::const_iterator found = std::find(mExpectedFolderIds.begin() , mExpectedFolderIds.end(), request_id);
|
||||
|
||||
uuid_vec_t::const_iterator folder_iter = content_ids.begin();
|
||||
uuid_vec_t::const_iterator folder_end = content_ids.end();
|
||||
while (folder_iter != folder_end)
|
||||
{
|
||||
std::list<LLUUID>::const_iterator found = std::find(mExpectedFolderIds.begin(), mExpectedFolderIds.end(), *folder_iter);
|
||||
if (found != mExpectedFolderIds.end())
|
||||
{
|
||||
mExpectedFolderIds.erase(found);
|
||||
}
|
||||
|
||||
LLViewerInventoryCategory* cat(gInventory.getCategory(*folder_iter));
|
||||
if (cat)
|
||||
{
|
||||
cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
|
||||
}
|
||||
if (response_id.isNull())
|
||||
{
|
||||
// Failed to fetch, get it individually
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo(*folder_iter, FT_RECURSIVE));
|
||||
}
|
||||
else
|
||||
{
|
||||
// push descendant back to verify they are fetched fully (ex: didn't encounter depth limit)
|
||||
LLInventoryModel::cat_array_t* categories(NULL);
|
||||
LLInventoryModel::item_array_t* items(NULL);
|
||||
gInventory.getDirectDescendentsOf(*folder_iter, categories, items);
|
||||
if (categories)
|
||||
{
|
||||
for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
folder_iter++;
|
||||
}
|
||||
|
||||
if (!mFetchFolderQueue.empty())
|
||||
{
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
}
|
||||
void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType fetch_type)
|
||||
{
|
||||
// Don't push_front on failure - there is a chance it was fired from inside bulkFetchViaAis
|
||||
incrFetchFolderCount(-1);
|
||||
std::list<LLUUID>::const_iterator found = std::find(mExpectedFolderIds.begin(), mExpectedFolderIds.end(), request_id);
|
||||
if (found != mExpectedFolderIds.end())
|
||||
{
|
||||
mExpectedFolderIds.erase(found);
|
||||
|
|
@ -480,32 +537,34 @@ void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_i
|
|||
if (response_id.isNull()) // Failure
|
||||
{
|
||||
LL_DEBUGS(LOG_INV , "AIS3") << "Failure response for folder " << request_id << LL_ENDL;
|
||||
if (recursion == FT_RECURSIVE)
|
||||
if (fetch_type == FT_RECURSIVE)
|
||||
{
|
||||
// A full recursive request failed.
|
||||
// Try requesting folder and nested content separately
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
mFetchFolderQueue.push_front(FetchQueueInfo(request_id, FT_CONTENT_RECURSIVE));
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo(request_id, FT_FOLDER_AND_CONTENT));
|
||||
}
|
||||
else if (recursion == FT_CONTENT_RECURSIVE)
|
||||
else if (fetch_type == FT_FOLDER_AND_CONTENT)
|
||||
{
|
||||
LL_WARNS() << "Failed to download folder: " << request_id << " Requesting known content separately" << LL_ENDL;
|
||||
request_descendants = true;
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo(request_id, FT_CONTENT_RECURSIVE));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (recursion == FT_CONTENT_RECURSIVE || recursion == FT_RECURSIVE)
|
||||
if (fetch_type == FT_RECURSIVE)
|
||||
{
|
||||
// Got the folder, now recursively request content
|
||||
// Got the folder and content, now verify content
|
||||
// Request content even for FT_RECURSIVE in case of changes, failures
|
||||
// or if depth limit gets imlemented.
|
||||
// This shouldn't redownload folders if they already have version
|
||||
request_descendants = true;
|
||||
LL_DEBUGS(LOG_INV, "AIS3") << "Got folder " << request_id << ". Requesting content" << LL_ENDL;
|
||||
}
|
||||
else if (fetch_type == FT_FOLDER_AND_CONTENT)
|
||||
{
|
||||
// readd folder for content request
|
||||
mFetchFolderQueue.push_front(FetchQueueInfo(request_id, FT_CONTENT_RECURSIVE));
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS(LOG_INV, "AIS3") << "Got folder " << request_id << "." << LL_ENDL;
|
||||
|
|
@ -524,17 +583,18 @@ void LLInventoryModelBackgroundFetch::onAISFolderCalback(const LLUUID &request_i
|
|||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
mFetchFolderQueue.push_front(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE));
|
||||
}
|
||||
if (!mFetchFolderQueue.empty())
|
||||
{
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mFetchFolderQueue.empty())
|
||||
{
|
||||
mBackgroundFetchActive = true;
|
||||
mFolderFetchActive = true;
|
||||
gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);
|
||||
}
|
||||
|
||||
// done
|
||||
LLViewerInventoryCategory * cat(gInventory.getCategory(request_id));
|
||||
if (cat)
|
||||
|
|
@ -555,9 +615,9 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis()
|
|||
}
|
||||
|
||||
static LLCachedControl<U32> ais_pool(gSavedSettings, "PoolSizeAIS", 20);
|
||||
// Don't have too many requests at once
|
||||
// Don't have too many requests at once, AIS throttles
|
||||
// Reserve one request for actions outside of fetch (like renames)
|
||||
const U32 max_concurrent_fetches = llmax(1, ais_pool - 1);
|
||||
const U32 max_concurrent_fetches = llclamp(ais_pool - 1, 1, 50);
|
||||
|
||||
if (mFetchCount >= max_concurrent_fetches)
|
||||
{
|
||||
|
|
@ -663,10 +723,97 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc
|
|||
LLViewerInventoryCategory * cat(gInventory.getCategory(cat_id));
|
||||
if (cat)
|
||||
{
|
||||
if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion() || fetch_info.mFetchType == FT_FORCED)
|
||||
if (fetch_info.mFetchType == FT_CONTENT_RECURSIVE)
|
||||
{
|
||||
// fetch content only, ignore cat itself
|
||||
uuid_vec_t children;
|
||||
LLInventoryModel::cat_array_t* categories(NULL);
|
||||
LLInventoryModel::item_array_t* items(NULL);
|
||||
gInventory.getDirectDescendentsOf(cat_id, categories, items);
|
||||
|
||||
LLViewerInventoryCategory::EFetchType target_state =
|
||||
fetch_info.mFetchType > FT_CONTENT_RECURSIVE
|
||||
? LLViewerInventoryCategory::FETCH_RECURSIVE
|
||||
: LLViewerInventoryCategory::FETCH_NORMAL;
|
||||
// technically limit is 'as many as you can put into url', but for now stop at 10
|
||||
const S32 batch_limit = 10;
|
||||
bool content_done = true;
|
||||
|
||||
for (LLInventoryModel::cat_array_t::iterator it = categories->begin();
|
||||
it != categories->end();
|
||||
++it)
|
||||
{
|
||||
LLViewerInventoryCategory* child_cat = (*it);
|
||||
if (LLViewerInventoryCategory::VERSION_UNKNOWN != child_cat->getVersion()
|
||||
|| child_cat->getFetching() >= target_state)
|
||||
{
|
||||
// push it back to verify everything inside is fetched
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo((*it)->getUUID(), FT_RECURSIVE));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child_cat->getPreferredType() == LLFolderType::FT_MARKETPLACE_LISTINGS)
|
||||
{
|
||||
// special case
|
||||
content_done = false;
|
||||
if (children.empty())
|
||||
{
|
||||
// fetch marketplace alone
|
||||
children.push_back(child_cat->getUUID());
|
||||
mExpectedFolderIds.push_back(child_cat->getUUID());
|
||||
child_cat->setFetching(target_state);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// fetch marketplace alone next run
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
children.push_back(child_cat->getUUID());
|
||||
mExpectedFolderIds.push_back(child_cat->getUUID());
|
||||
child_cat->setFetching(target_state);
|
||||
|
||||
if (children.size() >= batch_limit)
|
||||
{
|
||||
content_done = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!children.empty())
|
||||
{
|
||||
// increment before call in case of immediate callback
|
||||
incrFetchFolderCount(1);
|
||||
|
||||
EFetchType type = fetch_info.mFetchType;
|
||||
LLUUID cat_id = cat->getUUID(); // need a copy for lambda
|
||||
AISAPI::completion_t cb = [cat_id, children, type](const LLUUID& response_id)
|
||||
{
|
||||
LLInventoryModelBackgroundFetch::instance().onAISContentCalback(cat_id, children, response_id, type);
|
||||
};
|
||||
|
||||
AISAPI::ITEM_TYPE item_type = AISAPI::INVENTORY;
|
||||
if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
|
||||
{
|
||||
item_type = AISAPI::LIBRARY;
|
||||
}
|
||||
|
||||
AISAPI::FetchCategorySubset(cat_id, children, item_type, true, cb, 0);
|
||||
}
|
||||
|
||||
if (!content_done)
|
||||
{
|
||||
// send it back to get the rest
|
||||
mFetchFolderQueue.push_back(FetchQueueInfo(cat_id, FT_CONTENT_RECURSIVE));
|
||||
}
|
||||
}
|
||||
else if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()
|
||||
|| fetch_info.mFetchType == FT_FORCED)
|
||||
{
|
||||
LLViewerInventoryCategory::EFetchType target_state =
|
||||
fetch_info.mFetchType >= FT_CONTENT_RECURSIVE
|
||||
fetch_info.mFetchType > FT_CONTENT_RECURSIVE
|
||||
? LLViewerInventoryCategory::FETCH_RECURSIVE
|
||||
: LLViewerInventoryCategory::FETCH_NORMAL;
|
||||
// start again if we did a non-recursive fetch before
|
||||
|
|
@ -711,7 +858,7 @@ void LLInventoryModelBackgroundFetch::bulkFetchViaAis(const FetchQueueInfo& fetc
|
|||
}
|
||||
}
|
||||
}
|
||||
} // else?
|
||||
} // else try to fetch folder either way?
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -82,8 +82,9 @@ protected:
|
|||
|
||||
typedef enum {
|
||||
FT_DEFAULT = 0,
|
||||
FT_FORCED, // request even if already loaded
|
||||
FT_FORCED, // request non-recursively even if already loaded
|
||||
FT_CONTENT_RECURSIVE, // request content recursively
|
||||
FT_FOLDER_AND_CONTENT, // request content recursively
|
||||
FT_RECURSIVE, // request everything recursively
|
||||
} EFetchType;
|
||||
struct FetchQueueInfo
|
||||
|
|
@ -100,7 +101,8 @@ protected:
|
|||
};
|
||||
typedef std::deque<FetchQueueInfo> fetch_queue_t;
|
||||
|
||||
void onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType recursion);
|
||||
void onAISContentCalback(const LLUUID& request_id, const uuid_vec_t &content_ids, const LLUUID& response_id, EFetchType fetch_type);
|
||||
void onAISFolderCalback(const LLUUID &request_id, const LLUUID &response_id, EFetchType fetch_type);
|
||||
void bulkFetchViaAis();
|
||||
void bulkFetchViaAis(const FetchQueueInfo& fetch_info);
|
||||
void bulkFetch();
|
||||
|
|
|
|||
Loading…
Reference in New Issue