diff options
| author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2023-03-10 00:12:16 +0200 | 
|---|---|---|
| committer | akleshchev <117672381+akleshchev@users.noreply.github.com> | 2023-03-10 19:32:47 +0200 | 
| commit | ff6ff01c6a3822c8160279fecd3c3f2e636c4349 (patch) | |
| tree | e67c1726dea96dbe3d06a69eb799265f9a984ea9 | |
| parent | 811da7dbb1bdbf04a2dceb02ad4d296db4274076 (diff) | |
SL-18629 Replacing UDP creation messages with callback based AIS
| -rw-r--r-- | indra/newview/llaisapi.cpp | 17 | ||||
| -rw-r--r-- | indra/newview/llfloatermarketplacelistings.cpp | 7 | ||||
| -rw-r--r-- | indra/newview/llinventorybridge.cpp | 131 | ||||
| -rw-r--r-- | indra/newview/llinventoryfunctions.cpp | 229 | ||||
| -rw-r--r-- | indra/newview/llinventoryfunctions.h | 47 | ||||
| -rw-r--r-- | indra/newview/llinventorymodel.cpp | 110 | ||||
| -rw-r--r-- | indra/newview/llinventorymodel.h | 2 | ||||
| -rw-r--r-- | indra/newview/llmarketplacefunctions.cpp | 6 | 
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();          }  | 
