summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llaisapi.cpp17
-rw-r--r--indra/newview/llfloatermarketplacelistings.cpp7
-rw-r--r--indra/newview/llinventorybridge.cpp131
-rw-r--r--indra/newview/llinventoryfunctions.cpp229
-rw-r--r--indra/newview/llinventoryfunctions.h47
-rw-r--r--indra/newview/llinventorymodel.cpp110
-rw-r--r--indra/newview/llinventorymodel.h2
-rw-r--r--indra/newview/llmarketplacefunctions.cpp6
8 files changed, 369 insertions, 180 deletions
diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index d2c59cfaba..3826da0341 100644
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -93,6 +93,7 @@ void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, c
if (cap.empty())
{
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
+ callback(LLUUID::null);
return;
}
@@ -485,13 +486,17 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
{
LLUUID id(LLUUID::null);
- if (result.has("category_id") && (type == COPYLIBRARYCATEGORY))
+ if (type == COPYLIBRARYCATEGORY)
{
- id = result["category_id"];
+ if (result.has("category_id"))
+ {
+ id = result["category_id"];
+ } //else signal failure
callback(id);
}
if (type == CREATEINVENTORY)
{
+ bool informed_caller = false;
if (result.has("_created_categories"))
{
LLSD& cats = result["_created_categories"];
@@ -500,6 +505,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
{
LLUUID cat_id = *cat_iter;
callback(cat_id);
+ informed_caller = true;
}
}
if (result.has("_created_items"))
@@ -510,8 +516,15 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
{
LLUUID item_id = *item_iter;
callback(item_id);
+ informed_caller = true;
}
}
+
+ if (!informed_caller)
+ {
+ // signal failure with null id
+ callback(id);
+ }
}
}
diff --git a/indra/newview/llfloatermarketplacelistings.cpp b/indra/newview/llfloatermarketplacelistings.cpp
index 9110d9e902..b547150b56 100644
--- a/indra/newview/llfloatermarketplacelistings.cpp
+++ b/indra/newview/llfloatermarketplacelistings.cpp
@@ -896,8 +896,11 @@ void LLFloaterMarketplaceValidation::onOpen(const LLSD& key)
// Validates the folder
if (cat_id.notNull())
{
- LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id);
- validate_marketplacelistings(cat, boost::bind(&LLFloaterMarketplaceValidation::appendMessage, this, _1, _2, _3), false);
+ LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
+ cat_id,
+ NULL,
+ boost::bind(&LLFloaterMarketplaceValidation::appendMessage, this, _1, _2, _3),
+ false);
}
// Handle the listing folder being processed
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index fb92437c3d..b4d7762613 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -2901,11 +2901,16 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid);
if (version_folder_id.notNull())
{
- LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id);
- if (!validate_marketplacelistings(cat,NULL))
+ LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
+ version_folder_id,
+ [version_folder_id](bool result)
{
- LLMarketplaceData::instance().activateListing(version_folder_id,false);
+ if (!result)
+ {
+ LLMarketplaceData::instance().activateListing(version_folder_id, false);
+ }
}
+ );
}
// In all cases, update the listing we moved from so suffix are updated
update_marketplace_category(from_folder_uuid);
@@ -3371,18 +3376,26 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
if (depth_nesting_in_marketplace(mUUID) == 1)
{
LLUUID version_folder_id = LLMarketplaceData::instance().getVersionFolder(mUUID);
- LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id);
mMessage = "";
- if (!validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3)))
- {
- LLSD subs;
- subs["[ERROR_CODE]"] = mMessage;
- LLNotificationsUtil::add("MerchantListingFailed", subs);
- }
- else
+
+ LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
+ version_folder_id,
+ [this, version_folder_id](bool result)
{
- LLMarketplaceData::instance().activateListing(mUUID,true);
- }
+ // todo: might need to ensure bridge/mUUID exists or this will cause crashes
+ if (!result)
+ {
+ LLSD subs;
+ subs["[ERROR_CODE]"] = mMessage;
+ LLNotificationsUtil::add("MerchantListingFailed", subs);
+ }
+ else
+ {
+ LLMarketplaceData::instance().activateListing(mUUID, true);
+ }
+ },
+ boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3)
+ );
}
return;
}
@@ -3390,18 +3403,27 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
{
if (depth_nesting_in_marketplace(mUUID) == 2)
{
- LLInventoryCategory* category = gInventory.getCategory(mUUID);
mMessage = "";
- if (!validate_marketplacelistings(category,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),false,2))
- {
- LLSD subs;
- subs["[ERROR_CODE]"] = mMessage;
- LLNotificationsUtil::add("MerchantFolderActivationFailed", subs);
- }
- else
+
+ LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
+ mUUID,
+ [this](bool result)
{
- LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), mUUID);
- }
+ if (!result)
+ {
+ LLSD subs;
+ subs["[ERROR_CODE]"] = mMessage;
+ LLNotificationsUtil::add("MerchantFolderActivationFailed", subs);
+ }
+ else
+ {
+ LLInventoryCategory* category = gInventory.getCategory(mUUID);
+ LLMarketplaceData::instance().setVersionFolder(category->getParentUUID(), mUUID);
+ }
+ },
+ boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),
+ false,
+ 2);
}
return;
}
@@ -3424,29 +3446,44 @@ void LLFolderBridge::performAction(LLInventoryModel* model, std::string action)
}
else if ("marketplace_create_listing" == action)
{
- LLViewerInventoryCategory* cat = gInventory.getCategory(mUUID);
mMessage = "";
- bool validates = validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),false);
- if (!validates)
+
+ // first run vithout fix_hierarchy, second run with fix_hierarchy
+ LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
+ mUUID,
+ [this](bool result)
{
- mMessage = "";
- validates = validate_marketplacelistings(cat,boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),true);
- if (validates)
+ if (!result)
+ {
+ mMessage = "";
+
+ LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
+ mUUID,
+ [this](bool result)
+ {
+ if (result)
+ {
+ LLNotificationsUtil::add("MerchantForceValidateListing");
+ LLMarketplaceData::instance().createListing(mUUID);
+ }
+ else
+ {
+ LLSD subs;
+ subs["[ERROR_CODE]"] = mMessage;
+ LLNotificationsUtil::add("MerchantListingFailed", subs);
+ }
+ },
+ boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),
+ true);
+ }
+ else
{
- LLNotificationsUtil::add("MerchantForceValidateListing");
+ LLMarketplaceData::instance().createListing(mUUID);
}
- }
+ },
+ boost::bind(&LLFolderBridge::gatherMessage, this, _1, _2, _3),
+ false);
- if (!validates)
- {
- LLSD subs;
- subs["[ERROR_CODE]"] = mMessage;
- LLNotificationsUtil::add("MerchantListingFailed", subs);
- }
- else
- {
- LLMarketplaceData::instance().createListing(mUUID);
- }
return;
}
else if ("marketplace_disassociate_listing" == action)
@@ -5296,11 +5333,15 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
LLUUID version_folder_id = LLMarketplaceData::instance().getActiveFolder(from_folder_uuid);
if (version_folder_id.notNull())
{
- LLViewerInventoryCategory* cat = gInventory.getCategory(version_folder_id);
- if (!validate_marketplacelistings(cat,NULL))
+ LLMarketplaceValidator::getInstance()->validateMarketplaceListings(
+ version_folder_id,
+ [version_folder_id](bool result)
{
- LLMarketplaceData::instance().activateListing(version_folder_id,false);
- }
+ if (!result)
+ {
+ LLMarketplaceData::instance().activateListing(version_folder_id, false);
+ }
+ });
}
}
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 6b406c4c9c..5975cb982b 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -1492,7 +1492,7 @@ bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUU
// Reparent the folder
gInventory.changeCategoryParent(viewer_inv_cat, dest_folder, false);
// Check the destination folder recursively for no copy items and promote the including folders if any
- validate_marketplacelistings(dest_cat);
+ LLMarketplaceValidator::getInstance()->validateMarketplaceListings(dest_folder);
}
// Update the modified folders
@@ -1517,32 +1517,23 @@ bool sort_alpha(const LLViewerInventoryCategory* cat1, const LLViewerInventoryCa
return cat1->getName().compare(cat2->getName()) < 0;
}
-void dump_trace(std::string& message, S32 depth, LLError::ELevel log_level)
-{
- LL_INFOS() << "validate_marketplacelistings : error = "<< log_level << ", depth = " << depth << ", message = " << message << LL_ENDL;
-}
-
// Make all relevant business logic checks on the marketplace listings starting with the folder as argument.
// This function does no deletion of listings but a mere audit and raises issues to the user (through the
-// optional callback cb). It also returns a boolean, true if things validate, false if issues are raised.
+// optional callback cb).
// The only inventory changes that are done is to move and sort folders containing no-copy items to stock folders.
-bool validate_marketplacelistings(
+// @pending_callbacks - how many callbacks we are waiting for, must be inited before use
+// @result - true if things validate, false if issues are raised, must be inited before use
+typedef boost::function<void(S32 pending_callbacks, bool result)> validation_result_callback_t;
+void validate_marketplacelistings(
LLInventoryCategory* cat,
- validation_callback_t cb,
+ validation_result_callback_t cb_result,
+ LLMarketplaceValidator::validation_msg_callback_t cb_msg,
bool fix_hierarchy,
S32 depth,
- bool notify_observers)
+ bool notify_observers,
+ S32 &pending_callbacks,
+ bool &result)
{
-#if 0
- // Used only for debug
- if (!cb)
- {
- cb = boost::bind(&dump_trace, _1, _2, _3);
- }
-#endif
- // Folder is valid unless issue is raised
- bool result = true;
-
// Get the type and the depth of the folder
LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (cat);
const LLFolderType::EType folder_type = cat->getPreferredType();
@@ -1574,10 +1565,10 @@ bool validate_marketplacelistings(
if (!can_move_folder_to_marketplace(cat, cat, cat, message, 0, fix_hierarchy))
{
result = false;
- if (cb)
+ if (cb_msg)
{
message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error") + " " + message;
- cb(message,depth,LLError::LEVEL_ERROR);
+ cb_msg(message,depth,LLError::LEVEL_ERROR);
}
}
}
@@ -1587,26 +1578,42 @@ bool validate_marketplacelistings(
{
if (fix_hierarchy)
{
- if (cb)
+ if (cb_msg)
{
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Warning") + " " + LLTrans::getString("Marketplace Validation Warning Stock");
- cb(message,depth,LLError::LEVEL_WARN);
+ cb_msg(message,depth,LLError::LEVEL_WARN);
}
+
// Nest the stock folder one level deeper in a normal folder and restart from there
+ pending_callbacks++;
LLUUID parent_uuid = cat->getParentUUID();
- LLUUID folder_uuid = gInventory.createNewCategory(parent_uuid, LLFolderType::FT_NONE, cat->getName());
- LLInventoryCategory* new_cat = gInventory.getCategory(folder_uuid);
- gInventory.changeCategoryParent(viewer_cat, folder_uuid, false);
- result &= validate_marketplacelistings(new_cat, cb, fix_hierarchy, depth + 1, notify_observers);
- return result;
+ LLUUID cat_uuid = cat->getUUID();
+ gInventory.createNewCategory(parent_uuid,
+ LLFolderType::FT_NONE,
+ cat->getName(),
+ [cat_uuid, cb_result, cb_msg, fix_hierarchy, depth, notify_observers](const LLUUID &new_cat_id)
+ {
+ LLInventoryCategory * move_cat = gInventory.getCategory(cat_uuid);
+ LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *)(move_cat);
+ LLInventoryCategory * new_cat = gInventory.getCategory(new_cat_id);
+ gInventory.changeCategoryParent(viewer_cat, new_cat_id, false);
+ S32 pending = 0;
+ bool result = true;
+ // notify_observers probably should be true in such case?
+ validate_marketplacelistings(new_cat, cb_result, cb_msg, fix_hierarchy, depth + 1, notify_observers, pending, result);
+ cb_result(pending, result);
+ }
+ );
+ result = false;
+ return;
}
else
{
result = false;
- if (cb)
+ if (cb_msg)
{
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error") + " " + LLTrans::getString("Marketplace Validation Warning Stock");
- cb(message,depth,LLError::LEVEL_ERROR);
+ cb_msg(message,depth,LLError::LEVEL_ERROR);
}
}
}
@@ -1637,10 +1644,10 @@ bool validate_marketplacelistings(
if (!can_move_to_marketplace(item, error_msg, false))
{
has_bad_items = true;
- if (cb && fix_hierarchy)
+ if (cb_msg && fix_hierarchy)
{
std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error") + " " + error_msg;
- cb(message,depth,LLError::LEVEL_ERROR);
+ cb_msg(message,depth,LLError::LEVEL_ERROR);
}
continue;
}
@@ -1671,35 +1678,35 @@ bool validate_marketplacelistings(
if (depth == 2)
{
// If this is an empty version folder, warn only (listing won't be delivered by AIS, but only AIS should unlist)
- if (cb)
+ if (cb_msg)
{
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Empty Version");
- cb(message,depth,LLError::LEVEL_WARN);
+ cb_msg(message,depth,LLError::LEVEL_WARN);
}
}
else if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2))
{
// If this is a legit but empty stock folder, warn only (listing must stay searchable when out of stock)
- if (cb)
+ if (cb_msg)
{
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Empty Stock");
- cb(message,depth,LLError::LEVEL_WARN);
+ cb_msg(message,depth,LLError::LEVEL_WARN);
}
}
- else if (cb)
+ else if (cb_msg)
{
// We warn if there's nothing in a regular folder (may be it's an under construction listing)
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Warning Empty");
- cb(message,depth,LLError::LEVEL_WARN);
+ cb_msg(message,depth,LLError::LEVEL_WARN);
}
}
else
{
// Done with that folder : Print out the folder name unless we already found an error here
- if (cb && result && (depth >= 1))
+ if (cb_msg && result && (depth >= 1))
{
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log");
- cb(message,depth,LLError::LEVEL_INFO);
+ cb_msg(message,depth,LLError::LEVEL_INFO);
}
}
}
@@ -1707,10 +1714,10 @@ bool validate_marketplacelistings(
else if ((count == 1) && !has_bad_items && (((unique_key == default_key) && (depth > 1)) || ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (depth > 2) && (cat_array->size() == 0))))
{
// Done with that folder : Print out the folder name unless we already found an error here
- if (cb && result && (depth >= 1))
+ if (cb_msg && result && (depth >= 1))
{
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log");
- cb(message,depth,LLError::LEVEL_INFO);
+ cb_msg(message,depth,LLError::LEVEL_INFO);
}
}
else
@@ -1732,11 +1739,11 @@ bool validate_marketplacelistings(
while (items_vector_it != items_vector.end())
{
// Create a new folder
- LLUUID parent_uuid = (depth > 2 ? viewer_cat->getParentUUID() : viewer_cat->getUUID());
+ const LLUUID parent_uuid = (depth > 2 ? viewer_cat->getParentUUID() : viewer_cat->getUUID());
LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(items_vector_it->second.back());
std::string folder_name = (depth >= 1 ? viewer_cat->getName() : viewer_inv_item->getName());
LLFolderType::EType new_folder_type = (items_vector_it->first == default_key ? LLFolderType::FT_NONE : LLFolderType::FT_MARKETPLACE_STOCK);
- if (cb)
+ if (cb_msg)
{
std::string message = "";
if (new_folder_type == LLFolderType::FT_MARKETPLACE_STOCK)
@@ -1747,24 +1754,31 @@ bool validate_marketplacelistings(
{
message = indent + folder_name + LLTrans::getString("Marketplace Validation Warning Create Version");
}
- cb(message,depth,LLError::LEVEL_WARN);
+ cb_msg(message,depth,LLError::LEVEL_WARN);
}
- std::vector<LLUUID> &uuid_vector = items_vector_it->second;
+
+ pending_callbacks++;
+ std::vector<LLUUID> uuid_vector = items_vector_it->second; // needs to be a copy for lambda
gInventory.createNewCategory(
parent_uuid,
new_folder_type,
folder_name,
- [uuid_vector, cb, indent, depth, parent_uuid, notify_observers](const LLUUID &new_category_id)
+ [uuid_vector, cb_result, cb_msg, depth, parent_uuid, notify_observers](const LLUUID &new_category_id)
{
// Move each item to the new folder
- std::vector<LLUUID>::reverse_iterator iter = uuid_vector.rbegin();
+ std::vector<LLUUID>::const_reverse_iterator iter = uuid_vector.rbegin();
while (iter != uuid_vector.rend())
{
LLViewerInventoryItem* viewer_inv_item = gInventory.getItem(*iter);
- if (cb)
+ if (cb_msg)
{
+ std::string indent;
+ for (int i = 1; i < depth; i++)
+ {
+ indent += " ";
+ }
std::string message = indent + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Move");
- cb(message, depth, LLError::LEVEL_WARN);
+ cb_msg(message, depth, LLError::LEVEL_WARN);
}
gInventory.changeItemParent(viewer_inv_item, new_category_id, true);
iter++;
@@ -1777,6 +1791,7 @@ bool validate_marketplacelistings(
{
gInventory.notifyObservers();
}
+ cb_result(0, true);
}
);
items_vector_it++;
@@ -1792,11 +1807,11 @@ bool validate_marketplacelistings(
{
LLViewerInventoryCategory * viewer_cat = (LLViewerInventoryCategory *) (*iter);
gInventory.changeCategoryParent(viewer_cat, parent_uuid, false);
- result &= validate_marketplacelistings(viewer_cat, cb, fix_hierarchy, depth, false);
+ validate_marketplacelistings(viewer_cat, cb_result, cb_msg, fix_hierarchy, depth, false, pending_callbacks, result);
}
}
}
- else if (cb)
+ else if (cb_msg)
{
// We are not fixing the hierarchy but reporting problems, report everything we can find
// Print the folder name
@@ -1807,20 +1822,20 @@ bool validate_marketplacelistings(
// Report if a stock folder contains a mix of items
result = false;
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Mixed Stock");
- cb(message,depth,LLError::LEVEL_ERROR);
+ cb_msg(message,depth,LLError::LEVEL_ERROR);
}
else if ((folder_type == LLFolderType::FT_MARKETPLACE_STOCK) && (cat_array->size() != 0))
{
// Report if a stock folder contains subfolders
result = false;
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Error Subfolder In Stock");
- cb(message,depth,LLError::LEVEL_ERROR);
+ cb_msg(message,depth,LLError::LEVEL_ERROR);
}
else
{
// Simply print the folder name
std::string message = indent + cat->getName() + LLTrans::getString("Marketplace Validation Log");
- cb(message,depth,LLError::LEVEL_INFO);
+ cb_msg(message,depth,LLError::LEVEL_INFO);
}
}
// Scan each item and report if there's a problem
@@ -1835,21 +1850,21 @@ bool validate_marketplacelistings(
// Report items that shouldn't be there to start with
result = false;
std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error") + " " + error_msg;
- cb(message,depth,LLError::LEVEL_ERROR);
+ cb_msg(message,depth,LLError::LEVEL_ERROR);
}
else if ((!viewer_inv_item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) && (folder_type != LLFolderType::FT_MARKETPLACE_STOCK))
{
// Report stock items that are misplaced
result = false;
std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Error Stock Item");
- cb(message,depth,LLError::LEVEL_ERROR);
+ cb_msg(message,depth,LLError::LEVEL_ERROR);
}
else if (depth == 1)
{
// Report items not wrapped in version folder
result = false;
std::string message = indent + " " + viewer_inv_item->getName() + LLTrans::getString("Marketplace Validation Warning Unwrapped Item");
- cb(message,depth,LLError::LEVEL_ERROR);
+ cb_msg(message,depth,LLError::LEVEL_ERROR);
}
}
}
@@ -1858,17 +1873,18 @@ bool validate_marketplacelistings(
if (viewer_cat->getDescendentCount() == 0)
{
// Remove the current folder if it ends up empty
- if (cb)
+ if (cb_msg)
{
std::string message = indent + viewer_cat->getName() + LLTrans::getString("Marketplace Validation Warning Delete");
- cb(message,depth,LLError::LEVEL_WARN);
+ cb_msg(message,depth,LLError::LEVEL_WARN);
}
gInventory.removeCategory(cat->getUUID());
if (notify_observers)
{
gInventory.notifyObservers();
}
- return result && !has_bad_items;
+ result &=!has_bad_items;
+ return;
}
}
@@ -1881,15 +1897,15 @@ bool validate_marketplacelistings(
for (LLInventoryModel::cat_array_t::iterator iter = cat_array_copy.begin(); iter != cat_array_copy.end(); iter++)
{
LLInventoryCategory* category = *iter;
- result &= validate_marketplacelistings(category, cb, fix_hierarchy, depth + 1, false);
+ validate_marketplacelistings(category, cb_result, cb_msg, fix_hierarchy, depth + 1, false, pending_callbacks, result);
}
-
+
update_marketplace_category(cat->getUUID(), true, true);
if (notify_observers)
{
gInventory.notifyObservers();
}
- return result && !has_bad_items;
+ result &= !has_bad_items;
}
void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id)
@@ -1989,8 +2005,91 @@ void move_items_to_new_subfolder(const uuid_vec_t& selected_uuids, const std::st
inventory_func_type func = boost::bind(&move_items_to_folder, _1, selected_uuids);
gInventory.createNewCategory(first_item->getParentUUID(), LLFolderType::FT_NONE, folder_name, func);
+}
+
+///----------------------------------------------------------------------------
+/// LLMarketplaceValidator implementations
+///----------------------------------------------------------------------------
+
+LLMarketplaceValidator::LLMarketplaceValidator()
+{
}
+LLMarketplaceValidator::~LLMarketplaceValidator()
+{
+}
+
+void LLMarketplaceValidator::validateMarketplaceListings(
+ const LLUUID &category_id,
+ LLMarketplaceValidator::validation_done_callback_t cb_done,
+ LLMarketplaceValidator::validation_msg_callback_t cb_msg,
+ bool fix_hierarchy,
+ S32 depth)
+{
+
+ mValidationQueue.emplace(category_id, cb_done, cb_msg, fix_hierarchy, depth);
+ if (!mValidationInProgress)
+ {
+ start();
+ }
+}
+
+void LLMarketplaceValidator::start()
+{
+ if (mValidationQueue.empty())
+ {
+ mValidationInProgress = false;
+ return;
+ }
+ mValidationInProgress = true;
+ mPendingCallbacks = 1; // do '1' in case something decides ro callback immediately
+ const ValidationRequest &first = mValidationQueue.front();
+ LLViewerInventoryCategory* cat = gInventory.getCategory(first.mCategoryId);
+
+ validation_result_callback_t result_callback = [](S32 pending, bool result)
+ {
+ LLMarketplaceValidator* validator = LLMarketplaceValidator::getInstance();
+ validator->mPendingCallbacks--; // we just got a callback
+ validator->mPendingCallbacks += pending;
+ validator->mPendingResult &= result;
+ if (validator->mPendingCallbacks <= 0)
+ {
+ llassert(validator->mPendingCallbacks == 0); // shouldn't be below 0
+ const ValidationRequest &first = validator->mValidationQueue.front();
+ if (first.mCbDone)
+ {
+ first.mCbDone(validator->mPendingResult);
+ }
+ validator->mValidationQueue.pop(); // done;
+ validator->start();
+ }
+ };
+
+ validate_marketplacelistings(
+ cat,
+ result_callback,
+ first.mCbMsg,
+ first.mFixHierarchy,
+ first.mDepth,
+ true,
+ mPendingCallbacks,
+ mPendingResult);
+
+ result_callback(mPendingCallbacks, mPendingResult);
+}
+
+LLMarketplaceValidator::ValidationRequest::ValidationRequest(
+ LLUUID category_id,
+ validation_done_callback_t cb_done,
+ validation_msg_callback_t cb_msg,
+ bool fix_hierarchy,
+ S32 depth)
+: mCategoryId(category_id)
+, mCbDone(cb_done)
+, mCbMsg(cb_msg)
+, mFixHierarchy(fix_hierarchy)
+, mDepth(depth)
+{}
///----------------------------------------------------------------------------
/// LLInventoryCollectFunctor implementations
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 56ad6f6496..ec5e53f9a6 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -81,13 +81,12 @@ void copy_inventory_category_content(const LLUUID& new_cat_uuid, LLInventoryMode
// Generates a string containing the path to the item specified by item_id.
void append_path(const LLUUID& id, std::string& path);
-typedef boost::function<void(std::string& validation_message, S32 depth, LLError::ELevel log_level)> validation_callback_t;
bool can_move_item_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryItem* inv_item, std::string& tooltip_msg, S32 bundle_size = 1, bool from_paste = false);
bool can_move_folder_to_marketplace(const LLInventoryCategory* root_folder, LLInventoryCategory* dest_folder, LLInventoryCategory* inv_cat, std::string& tooltip_msg, S32 bundle_size = 1, bool check_items = true, bool from_paste = false);
bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_folder, bool copy = false);
bool move_folder_to_marketplacelistings(LLInventoryCategory* inv_cat, const LLUUID& dest_folder, bool copy = false, bool move_no_copy_items = false);
-bool validate_marketplacelistings(LLInventoryCategory* inv_cat, validation_callback_t cb = NULL, bool fix_hierarchy = true, S32 depth = -1, bool notify_observers = true);
+
S32 depth_nesting_in_marketplace(LLUUID cur_uuid);
LLUUID nested_parent_id(LLUUID cur_uuid, S32 depth);
S32 compute_stock_count(LLUUID cat_uuid, bool force_count = false);
@@ -102,6 +101,50 @@ bool is_only_items_selected(const uuid_vec_t& selected_uuids);
** **
*******************************************************************************/
+class LLMarketplaceValidator: public LLSingleton<LLMarketplaceValidator>
+{
+ LLSINGLETON(LLMarketplaceValidator);
+ ~LLMarketplaceValidator();
+ LOG_CLASS(LLMarketplaceValidator);
+public:
+
+ typedef boost::function<void(std::string& validation_message, S32 depth, LLError::ELevel log_level)> validation_msg_callback_t;
+ typedef boost::function<void(bool result)> validation_done_callback_t;
+
+ void validateMarketplaceListings(
+ const LLUUID &category_id,
+ validation_done_callback_t cb_done = NULL,
+ validation_msg_callback_t cb_msg = NULL,
+ bool fix_hierarchy = true,
+ S32 depth = -1);
+
+private:
+ void start();
+
+ class ValidationRequest
+ {
+ public:
+ ValidationRequest(
+ LLUUID category_id,
+ validation_done_callback_t cb_done,
+ validation_msg_callback_t cb_msg,
+ bool fix_hierarchy,
+ S32 depth);
+ LLUUID mCategoryId;
+ validation_done_callback_t mCbDone;
+ validation_msg_callback_t mCbMsg;
+ bool mFixHierarchy;
+ S32 mDepth;
+ };
+
+ bool mValidationInProgress;
+ S32 mPendingCallbacks;
+ bool mPendingResult;
+ // todo: might be a good idea to memorize requests by id and
+ // filter out ones that got multiple validation requests
+ std::queue<ValidationRequest> mValidationQueue;
+};
+
/********************************************************************************
** **
** INVENTORY COLLECTOR FUNCTIONS
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index b2cfc8584e..774ed051c0 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -954,27 +954,23 @@ const LLUUID LLInventoryModel::findLibraryCategoryUUIDForType(LLFolderType::ETyp
// Convenience function to create a new category. You could call
// updateCategory() with a newly generated UUID category, but this
// version will take care of details like what the name should be
-// based on preferred type. Returns the UUID of the new category.
-//
-// On failure, returns a null UUID.
-// FIXME: callers do not check for or handle a null results currently.
-LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
+// based on preferred type.
+void LLInventoryModel::createNewCategory(const LLUUID& parent_id,
LLFolderType::EType preferred_type,
const std::string& pname,
inventory_func_type callback)
{
- LLUUID id; // Initially null.
if (!isInventoryUsable())
{
LL_WARNS(LOG_INV) << "Inventory is not usable; can't create requested category of type "
<< preferred_type << LL_ENDL;
- return id;
+ return;
}
if(LLFolderType::lookup(preferred_type) == LLFolderType::badLookup())
{
LL_DEBUGS(LOG_INV) << "Attempt to create undefined category." << LL_ENDL;
- return id;
+ return;
}
if (preferred_type != LLFolderType::FT_NONE)
@@ -990,24 +986,53 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
{
name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
}
-
+
#ifdef USE_AIS_FOR_NC
- // D567 currently this doesn't really work due to limitations in
- // AIS3, also violates the common caller assumption that we can
- // assign the id and return immediately.
- if (callback)
+ // D567 currently this doesn't really work due to limitations in
+ // AIS3, also violates the common caller assumption that we can
+ // assign the id and return immediately.
+ if (callback && AISAPI::isAvailable())
{
- // D567 note that we no longer assign the UUID in the viewer, so various workflows need to change.
LLSD new_inventory = LLSD::emptyMap();
new_inventory["categories"] = LLSD::emptyArray();
LLViewerInventoryCategory cat(LLUUID::null, parent_id, preferred_type, name, gAgent.getID());
LLSD cat_sd = cat.asLLSD();
new_inventory["categories"].append(cat_sd);
- AISAPI::CreateInventory(parent_id, new_inventory, callback);
+ AISAPI::CreateInventory(
+ parent_id,
+ new_inventory,
+ [this, callback, parent_id, preferred_type, name] (const LLUUID& new_category)
+ {
+ if (new_category.isNull())
+ {
+ callback(new_category);
+ return;
+ }
+
+ LLViewerInventoryCategory* folderp = gInventory.getCategory(new_category);
+ if (!folderp)
+ {
+ // Add the category to the internal representation
+ LLPointer<LLViewerInventoryCategory> cat = new LLViewerInventoryCategory(
+ new_category,
+ parent_id,
+ preferred_type,
+ name,
+ gAgent.getID());
+
+ LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1);
+ accountForUpdate(update);
+
+ cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
+ cat->setDescendentCount(0);
+ updateCategory(cat);
+ }
- return LLUUID::null;
+ callback(new_category);
+ });
+ return;
}
-#else
+#endif
LLViewerRegion* viewer_region = gAgent.getRegion();
std::string url;
if ( viewer_region )
@@ -1016,7 +1041,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
if (!url.empty() && callback)
{
//Let's use the new capability.
-
+ LLUUID id;
id.generate();
LLSD request, body;
body["folder_id"] = id;
@@ -1030,48 +1055,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
LL_DEBUGS(LOG_INV) << "Creating category via request: " << ll_pretty_print_sd(request) << LL_ENDL;
LLCoros::instance().launch("LLInventoryModel::createNewCategoryCoro",
boost::bind(&LLInventoryModel::createNewCategoryCoro, this, url, body, callback));
-
- return LLUUID::null;
}
-#endif
-
-
- if (!gMessageSystem)
- {
- return LLUUID::null;
- }
-
- // D567 FIXME this UDP code path needs to be removed. Requires
- // reworking many of the callers to use callbacks rather than
- // assuming instant success.
-
- // Add the category to the internal representation
- LL_WARNS() << "D567 need to remove this usage" << LL_ENDL;
-
- id.generate();
- LLPointer<LLViewerInventoryCategory> cat =
- new LLViewerInventoryCategory(id, parent_id, preferred_type, name, gAgent.getID());
- cat->setVersion(LLViewerInventoryCategory::VERSION_INITIAL - 1); // accountForUpdate() will icrease version by 1
- cat->setDescendentCount(0);
- LLCategoryUpdate update(cat->getParentUUID(), 1);
- accountForUpdate(update);
- updateCategory(cat);
-
- LL_DEBUGS(LOG_INV) << "Creating category via UDP message CreateInventoryFolder, type " << preferred_type << LL_ENDL;
-
- // Create the category on the server. We do this to prevent people
- // from munging their protected folders.
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage("CreateInventoryFolder");
- msg->nextBlock("AgentData");
- msg->addUUID("AgentID", gAgent.getID());
- msg->addUUID(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlock("FolderData");
- cat->packMessage(msg);
- gAgent.sendReliableMessage();
-
- // return the folder id of the newly created folder
- return id;
}
void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inventory_func_type callback)
@@ -1095,12 +1079,20 @@ void LLInventoryModel::createNewCategoryCoro(std::string url, LLSD postData, inv
if (!status)
{
LL_WARNS() << "HTTP failure attempting to create category." << LL_ENDL;
+ if (callback)
+ {
+ callback(LLUUID::null);
+ }
return;
}
if (!result.has("folder_id"))
{
LL_WARNS() << "Malformed response contents" << ll_pretty_print_sd(result) << LL_ENDL;
+ if (callback)
+ {
+ callback(LLUUID::null);
+ }
return;
}
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 1fde5a3b2f..5f8db30390 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -477,7 +477,7 @@ public:
public:
// Returns the UUID of the new category. If you want to use the default
// name based on type, pass in a NULL to the 'name' parameter.
- LLUUID createNewCategory(const LLUUID& parent_id,
+ void createNewCategory(const LLUUID& parent_id,
LLFolderType::EType preferred_type,
const std::string& name,
inventory_func_type callback = NULL);
diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp
index 5b86f2cc4b..4038afc74c 100644
--- a/indra/newview/llmarketplacefunctions.cpp
+++ b/indra/newview/llmarketplacefunctions.cpp
@@ -700,10 +700,9 @@ void LLMarketplaceInventoryObserver::onIdleProcessQueue(void *userdata)
// If it's a folder known to the marketplace, let's check it's in proper shape
if (LLMarketplaceData::instance().isListed(*id_it) || LLMarketplaceData::instance().isVersionFolder(*id_it))
{
- LLInventoryCategory* cat = (LLInventoryCategory*)(obj);
// can trigger notifyObservers
// can cause more structural changes
- validate_marketplacelistings(cat);
+ LLMarketplaceValidator::getInstance()->validateMarketplaceListings(obj->getUUID());
}
}
else
@@ -1848,8 +1847,7 @@ void LLMarketplaceData::decrementValidationWaiting(const LLUUID& folder_id, S32
if (found->second <= 0)
{
mValidationWaitingList.erase(found);
- LLInventoryCategory *cat = gInventory.getCategory(folder_id);
- validate_marketplacelistings(cat);
+ LLMarketplaceValidator::getInstance()->validateMarketplaceListings(folder_id);
update_marketplace_category(folder_id);
gInventory.notifyObservers();
}