diff options
| -rw-r--r-- | indra/newview/llinventorymodel.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/llmarketplacefunctions.cpp | 126 | ||||
| -rw-r--r-- | indra/newview/llmarketplacefunctions.h | 1 | 
3 files changed, 87 insertions, 43 deletions
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 37500176ea..ace4de928e 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1838,7 +1838,8 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)          }          // Fix me: From DD-81, probably shouldn't be here, instead -        // should be somewhere in an observer +        // should be somewhere in an observer or in +        // LLMarketplaceInventoryObserver::onIdleProcessQueue          update_marketplace_category(referent, false);          if (mask & LLInventoryObserver::ADD) diff --git a/indra/newview/llmarketplacefunctions.cpp b/indra/newview/llmarketplacefunctions.cpp index 044c76ce2c..74616df079 100644 --- a/indra/newview/llmarketplacefunctions.cpp +++ b/indra/newview/llmarketplacefunctions.cpp @@ -30,6 +30,7 @@  #include "llagent.h"  #include "llbufferstream.h" +#include "llcallbacklist.h"  #include "llinventoryfunctions.h"  #include "llinventoryobserver.h"  #include "llnotificationsutil.h" @@ -605,20 +606,62 @@ public:  	LLMarketplaceInventoryObserver() {}  	virtual ~LLMarketplaceInventoryObserver() {}  	virtual void changed(U32 mask); + +private: +    static void onIdleProcessQueue(void *userdata); + +    // doesn't hold just marketplace related ids +    static std::set<LLUUID> sAddQueue; +    static std::set<LLUUID> sStructureQueue;  }; +std::set<LLUUID> LLMarketplaceInventoryObserver::sAddQueue; +std::set<LLUUID> LLMarketplaceInventoryObserver::sStructureQueue; +  void LLMarketplaceInventoryObserver::changed(U32 mask)  { -    // When things are added to the marketplace, we might need to re-validate and fix the containing listings -	if (mask & LLInventoryObserver::ADD) +    bool idle_running = !sAddQueue.empty() && !sStructureQueue.empty(); +    bool needs_idle = false; +	if (mask & LLInventoryObserver::ADD && LLMarketplaceData::instance().hasValidationWaiting())  	{ +        // When things are added to the marketplace, we might need to re-validate and fix the containing listings +        // just add whole list even if it contains items and non-marketplace folders          const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); -         -        std::set<LLUUID>::const_iterator id_it = changed_items.begin(); -        std::set<LLUUID>::const_iterator id_end = changed_items.end(); +        sAddQueue.insert(changed_items.begin(), changed_items.end()); +        needs_idle = true; +	} +     +	if (mask & (LLInventoryObserver::INTERNAL | LLInventoryObserver::STRUCTURE)) +	{ +        // When things are changed in the inventory, this can trigger a host of changes in the marketplace listings folder: +        // * stock counts changing : no copy items coming in and out will change the stock count on folders +        // * version and listing folders : moving those might invalidate the marketplace data itself +        // Since we should cannot raise inventory change while the observer is called (the list will be cleared +        // once observers are called) we need to raise a flag in the inventory to signal that things have been dirtied. +        const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); +        sStructureQueue.insert(changed_items.begin(), changed_items.end()); +        needs_idle = true; +	} + +    if (!idle_running && needs_idle) +    { +        gIdleCallbacks.addFunction(onIdleProcessQueue, NULL); +    } +} + +void LLMarketplaceInventoryObserver::onIdleProcessQueue(void *userdata) +{ +    U64 start_time = LLTimer::getTotalTime(); // microseconds +    const U64 MAX_PROCESSING_TIME = 1000; +    U64 stop_time = start_time + MAX_PROCESSING_TIME; + +    if (!sAddQueue.empty()) +    { +        std::set<LLUUID>::const_iterator id_it = sAddQueue.begin(); +        std::set<LLUUID>::const_iterator id_end = sAddQueue.end();          // First, count the number of items in this list...          S32 count = 0; -        for (;id_it != id_end; ++id_it) +        for (; id_it != id_end; ++id_it)          {              LLInventoryObject* obj = gInventory.getObject(*id_it);              if (obj && (LLAssetType::AT_CATEGORY != obj->getType())) @@ -629,56 +672,55 @@ void LLMarketplaceInventoryObserver::changed(U32 mask)          // Then, decrement the folders of that amount          // Note that of all of those, only one folder will be a listing folder (if at all).          // The other will be ignored by the decrement method. -        id_it = changed_items.begin(); -        for (;id_it != id_end; ++id_it) +        id_it = sAddQueue.begin(); +        for (; id_it != id_end; ++id_it)          {              LLInventoryObject* obj = gInventory.getObject(*id_it);              if (obj && (LLAssetType::AT_CATEGORY == obj->getType()))              { -                LLMarketplaceData::instance().decrementValidationWaiting(obj->getUUID(),count); +                // can trigger notifyObservers +                LLMarketplaceData::instance().decrementValidationWaiting(obj->getUUID(), count);              }          } -	} -     -    // When things are changed in the inventory, this can trigger a host of changes in the marketplace listings folder: -    // * stock counts changing : no copy items coming in and out will change the stock count on folders -    // * version and listing folders : moving those might invalidate the marketplace data itself -    // Since we should cannot raise inventory change while the observer is called (the list will be cleared -    // once observers are called) we need to raise a flag in the inventory to signal that things have been dirtied. -     -	if (mask & (LLInventoryObserver::INTERNAL | LLInventoryObserver::STRUCTURE)) -	{ -        const std::set<LLUUID>& changed_items = gInventory.getChangedIDs(); -     -        std::set<LLUUID>::const_iterator id_it = changed_items.begin(); -        std::set<LLUUID>::const_iterator id_end = changed_items.end(); -        for (;id_it != id_end; ++id_it) +        sAddQueue.clear(); +    } + +    std::set<LLUUID>::const_iterator id_it = sStructureQueue.begin(); +    while (id_it != sStructureQueue.end() && LLTimer::getTotalTime() < stop_time) +    { +        LLInventoryObject* obj = gInventory.getObject(*id_it); +        if (obj)          { -            LLInventoryObject* obj = gInventory.getObject(*id_it); -            if (obj) +            if (LLAssetType::AT_CATEGORY == obj->getType())              { -                if (LLAssetType::AT_CATEGORY == obj->getType()) +                // 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))                  { -                    // 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); -                        validate_marketplacelistings(cat); -                    } +                    LLInventoryCategory* cat = (LLInventoryCategory*)(obj); +                    // can trigger notifyObservers +                    // can cause more structural changes +                    validate_marketplacelistings(cat);                  } -                else +            } +            else +            { +                // If it's not a category, it's an item... +                LLInventoryItem* item = (LLInventoryItem*)(obj); +                // If it's a no copy item, we may need to update the label count of marketplace listings +                if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()))                  { -                    // If it's not a category, it's an item... -                    LLInventoryItem* item = (LLInventoryItem*)(obj); -                    // If it's a no copy item, we may need to update the label count of marketplace listings -                    if (!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) -                    { -                        LLMarketplaceData::instance().setDirtyCount(); -                    } +                    LLMarketplaceData::instance().setDirtyCount();                  }              }          } -	} +        id_it = sStructureQueue.erase(id_it); +    } + +    if (LLApp::isExiting() || sStructureQueue.empty()) +    { +        // Nothing to do anymore +        gIdleCallbacks.deleteFunction(onIdleProcessQueue, NULL); +    }  }  // Tuple == Item diff --git a/indra/newview/llmarketplacefunctions.h b/indra/newview/llmarketplacefunctions.h index fee9225f77..ec5de88189 100644 --- a/indra/newview/llmarketplacefunctions.h +++ b/indra/newview/llmarketplacefunctions.h @@ -240,6 +240,7 @@ public:      void setUpdating(const LLUUID& folder_id, bool isUpdating);      // Used to decide when to run a validation on listing folders +    bool hasValidationWaiting() { return mValidationWaitingList.size() > 0; }      void setValidationWaiting(const LLUUID& folder_id, S32 count);      void decrementValidationWaiting(const LLUUID& folder_id, S32 count = 1);  | 
