SL-20285 Sturdier cof and fixed link fetching

master
Andrey Kleshchev 2023-09-14 18:42:42 +03:00
parent b5c745185f
commit fa47e4402b
5 changed files with 70 additions and 72 deletions

View File

@ -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<LLViewerInventoryCategory> 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();
}
}

View File

@ -118,7 +118,7 @@ public:
void parseLink(const LLSD& link_map, S32 depth);
void parseItem(const LLSD& link_map);
void parseCategory(const LLSD& link_map, S32 depth);
void parseDescendentCount(const LLUUID& category_id, const LLSD& embedded);
void parseDescendentCount(const LLUUID& category_id, LLFolderType::EType type, const LLSD& embedded);
void parseEmbedded(const LLSD& embedded, S32 depth);
void parseEmbeddedLinks(const LLSD& links, S32 depth);
void parseEmbeddedItems(const LLSD& items);

View File

@ -4446,7 +4446,7 @@ public:
{
LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
if (!cat) continue;
if (!isCategoryComplete(cat))
if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
{
// CHECK IT: isCategoryComplete() checks both version and descendant count but
// fetch() only works for Unknown version and doesn't care about descentants,
@ -4456,6 +4456,12 @@ public:
cat->fetch(); //blindly fetch it without seeing if anything else is fetching it.
mIncomplete.push_back(*it); //Add to list of things being downloaded for this observer.
}
else if (!isCategoryComplete(cat))
{
LL_DEBUGS("Inventory") << "Categoty " << *it << " incomplete despite having version" << LL_ENDL;
LLInventoryModelBackgroundFetch::instance().scheduleFolderFetch(*it, true);
mIncomplete.push_back(*it);
}
else if (ais3)
{
LLInventoryModel::cat_array_t* cats;
@ -4484,10 +4490,7 @@ public:
if (incomplete_count > MAX_INDIVIDUAL_FETCH
|| (incomplete_count > 1 && complete_count == 0))
{
// To prevent premature removal from mIncomplete and
// since we are doing a full refetch anyway, mark unknown
cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN);
cat->fetch();
LLInventoryModelBackgroundFetch::instance().scheduleFolderFetch(*it, true);
mIncomplete.push_back(*it);
}
else
@ -4496,6 +4499,7 @@ public:
mComplete.push_back(*it);
}
}
// else should have been handled by isCategoryComplete
}
else
{
@ -4519,13 +4523,11 @@ public:
// What we do here is get the complete information on the
// items in the requested category, and set up an observer
// that will wait for that to happen.
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendents(mComplete.front(),
cat_array,
item_array,
LLInventoryModel::EXCLUDE_TRASH);
S32 count = item_array.size();
LLInventoryModel::cat_array_t* cats;
LLInventoryModel::item_array_t* items;
gInventory.getDirectDescendentsOf(mComplete.front(), cats, items);
S32 count = items->size();
if(!count)
{
LL_WARNS() << "Nothing fetched in category " << mComplete.front()
@ -4537,11 +4539,13 @@ public:
return;
}
LL_INFOS() << "stage1 got " << item_array.size() << " items, passing to stage2 " << LL_ENDL;
LLViewerInventoryCategory* cat = gInventory.getCategory(mComplete.front());
S32 version = cat ? cat->getVersion() : -2;
LL_INFOS() << "stage1, category " << mComplete.front() << " got " << count << " items, version " << version << " passing to stage2 " << LL_ENDL;
uuid_vec_t ids;
for(S32 i = 0; i < count; ++i)
{
ids.push_back(item_array.at(i)->getUUID());
ids.push_back(items->at(i)->getUUID());
}
gInventory.removeObserver(this);
@ -4570,14 +4574,14 @@ void callAfterCOFFetch(nullary_func_t cb)
{
LLUUID cat_id = LLAppearanceMgr::instance().getCOF();
LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
if (AISAPI::isAvailable())
{
if (AISAPI::isAvailable())
{
// Mark cof (update timer) so that background fetch won't request it
cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE);
// Assume that we have no relevant cache. Fetch cof, and items cof's links point to.
AISAPI::FetchCOF([cb](const LLUUID& id)
// Mark cof (update timer) so that background fetch won't request it
cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE);
// For reliability assume that we have no relevant cache, so
// fetch cof along with items cof's links point to.
AISAPI::FetchCOF([cb](const LLUUID& id)
{
cb();
LLUUID cat_id = LLAppearanceMgr::instance().getCOF();
@ -4587,18 +4591,12 @@ void callAfterCOFFetch(nullary_func_t cb)
cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
}
});
}
else
{
LL_WARNS() << "AIS API v3 not available, can't use AISAPI::FetchCOF" << LL_ENDL;
// startup should have marked folder as fetching, remove that
cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
callAfterCategoryFetch(cat_id, cb);
}
}
else
{
// Assume that cache is present. Process like a normal folder.
LL_INFOS() << "AIS API v3 not available, using callAfterCategoryFetch" << LL_ENDL;
// startup should have marked folder as fetching, remove that
cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
callAfterCategoryFetch(cat_id, cb);
}
}

View File

@ -243,6 +243,7 @@ void LLAttachmentsMgr::linkRecentlyArrivedAttachments()
if (LLAppearanceMgr::instance().getCOFVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
{
// Wait for cof to load
LL_DEBUGS_ONCE("Avatar") << "Received atachments, but cof isn't loaded yet, postponing processing" << LL_ENDL;
return;
}

View File

@ -334,21 +334,14 @@ void LLInventoryFetchItemsObserver::startFetch()
if (aisv3)
{
const S32 MAX_INDIVIDUAL_REQUESTS = 10;
const S32 MAX_INDIVIDUAL_REQUESTS = 7;
for (requests_by_folders_t::value_type &folder : requests)
{
LLViewerInventoryCategory* cat = gInventory.getCategory(folder.first);
if (folder.second.size() > MAX_INDIVIDUAL_REQUESTS)
{
// requesting one by one will take a while
// do whole folder
if (cat)
{
// Either drop version or use scheduleFolderFetch to force-fetch
// otherwise background fetch will ignore folders with set version
cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN);
}
LLInventoryModelBackgroundFetch::getInstance()->start(folder.first);
LLInventoryModelBackgroundFetch::getInstance()->scheduleFolderFetch(folder.first, true);
}
else
{
@ -360,12 +353,11 @@ void LLInventoryFetchItemsObserver::startFetch()
// start fetching whole folder since it's not ready either way
cat->fetch();
}
else if (cat->getViewerDescendentCount() <= folder.second.size())
else if (cat->getViewerDescendentCount() <= folder.second.size()
|| cat->getDescendentCount() <= folder.second.size())
{
// Start fetching whole folder since we need all items
// Drop version or use scheduleFolderFetch
cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN);
cat->fetch();
LLInventoryModelBackgroundFetch::getInstance()->scheduleFolderFetch(folder.first, true);
}
else
@ -382,6 +374,7 @@ void LLInventoryFetchItemsObserver::startFetch()
// Isn't supposed to happen? We should have all folders
// and if item exists, folder is supposed to exist as well.
llassert(false);
LL_WARNS("Inventory") << "Missing folder: " << folder.first << " fetching items individually" << LL_ENDL;
// get items one by one
for (LLUUID &item_id : folder.second)