From 0a6a5f63b45bf3d97c7926b8d415b0b3885f64a1 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 5 Apr 2013 13:44:33 -0400 Subject: SH-4061 WIP - spelling fix, allow un-set of missing asset flag for textures --- indra/newview/llviewertexture.cpp | 44 ++++++++++++++++++++++++--------------- indra/newview/llviewertexture.h | 2 +- indra/newview/llvoavatar.cpp | 6 +++--- indra/newview/llvoavatar.h | 2 +- indra/newview/llvoavatarself.cpp | 2 +- 5 files changed, 33 insertions(+), 23 deletions(-) mode change 100644 => 100755 indra/newview/llviewertexture.cpp mode change 100644 => 100755 indra/newview/llviewertexture.h (limited to 'indra/newview') diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp old mode 100644 new mode 100755 index eb6c453e76..500a6c8869 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2005,29 +2005,39 @@ void LLViewerFetchedTexture::forceToDeleteRequest() mDesiredDiscardLevel = getMaxDiscardLevel() + 1; } -void LLViewerFetchedTexture::setIsMissingAsset() +void LLViewerFetchedTexture::setIsMissingAsset(bool is_missing) { - if (mUrl.empty()) + if (is_missing) { - llwarns << mID << ": Marking image as missing" << llendl; + if (mUrl.empty()) + { + llwarns << mID << ": Marking image as missing" << llendl; + } + else + { + // This may or may not be an error - it is normal to have no + // map tile on an empty region, but bad if we're failing on a + // server bake texture. + if (getFTType() != FTT_MAP_TILE) + { + llwarns << mUrl << ": Marking image as missing" << llendl; + } + } + if (mHasFetcher) + { + LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); + mHasFetcher = FALSE; + mIsFetching = FALSE; + mLastPacketTimer.reset(); + mFetchState = 0; + mFetchPriority = 0; + } } else { - // This may or may not be an error - it is normal to have no - // map tile on an empty region, but bad if we're failing on a - // server bake texture. - llwarns << mUrl << ": Marking image as missing" << llendl; - } - if (mHasFetcher) - { - LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); - mHasFetcher = FALSE; - mIsFetching = FALSE; - mLastPacketTimer.reset(); - mFetchState = 0; - mFetchPriority = 0; + llinfos << mID << ": un-flagging missing asset" << llendl; } - mIsMissingAsset = TRUE; + mIsMissingAsset = is_missing; } void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback, diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h old mode 100644 new mode 100755 index f2e1a90713..1f2079104f --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -338,7 +338,7 @@ public: // more data. /*virtual*/ void setKnownDrawSize(S32 width, S32 height); - void setIsMissingAsset(); + void setIsMissingAsset(bool is_missing = true); /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } // returns dimensions of original image for local files (before power of two scaling) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 5695fc04b9..a71bb93ba2 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -4408,7 +4408,7 @@ void LLVOAvatar::addLocalTextureStats( ETextureIndex idx, LLViewerFetchedTexture } const S32 MAX_TEXTURE_UPDATE_INTERVAL = 64 ; //need to call updateTextures() at least every 32 frames. -const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL = S32_MAX ; //frames +const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL = S32_MAX ; //frames void LLVOAvatar::checkTextureLoading() { static const F32 MAX_INVISIBLE_WAITING_TIME = 15.f ; //seconds @@ -4471,11 +4471,11 @@ const F32 ADDITIONAL_PRI = 0.5f; void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level) { //Note: - //if this function is not called for the last MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL frames, + //if this function is not called for the last MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL frames, //the texture pipeline will stop fetching this texture. imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); imagep->resetMaxVirtualSizeResetCounter() ; mMaxPixelArea = llmax(pixel_area, mMaxPixelArea); diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 85f6f25009..98e8491cb1 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -991,7 +991,7 @@ protected: // Shared with LLVOAvatarSelf }; // LLVOAvatar extern const F32 SELF_ADDITIONAL_PRI; -extern const S32 MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL; +extern const S32 MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL; std::string get_sequential_numbered_file_name(const std::string& prefix, const std::string& suffix); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 0404884245..5f9b4a59e7 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2587,7 +2587,7 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe imagep->setBoostLevel(getAvatarBoostLevel()); imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; imagep->resetTextureStats(); - imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTURE_SIZE_RESET_INTERVAL); + imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); imagep->addTextureStats( desired_pixels / texel_area_ratio ); imagep->forceUpdateBindStats() ; if (imagep->getDiscardLevel() < 0) -- cgit v1.2.3 From e16435c37cb7410f3ea4596e30fd232ac558bc71 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 8 Apr 2013 13:26:05 -0400 Subject: SH-4061 WIP - added ability to un-set missing asset, do this in the case of FTT_SERVER_BAKE images. This is needed because 'missing' is not necessarily permanent for such images. --- indra/newview/llpaneloutfitsinventory.cpp | 3 ++- indra/newview/llviewertexture.cpp | 6 +++++- indra/newview/llviewertexture.h | 8 ++++---- indra/newview/llvoavatar.cpp | 4 ++++ 4 files changed, 15 insertions(+), 6 deletions(-) mode change 100644 => 100755 indra/newview/llpaneloutfitsinventory.cpp (limited to 'indra/newview') diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp old mode 100644 new mode 100755 index f90236f6f2..d6c927ab58 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -76,7 +76,8 @@ BOOL LLPanelOutfitsInventory::postBuild() // Fetch your outfits folder so that the links are in memory. // ( This is only necessary if we want to show a warning if a user deletes an item that has a // a link in an outfit, see "ConfirmItemDeleteHasLinks". ) - const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_OUTFIT, false); + + const LLUUID &outfits_cat = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS, false); if (outfits_cat.notNull()) { LLInventoryModelBackgroundFetch::instance().start(outfits_cat); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 500a6c8869..9cca8a244e 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -2005,8 +2005,12 @@ void LLViewerFetchedTexture::forceToDeleteRequest() mDesiredDiscardLevel = getMaxDiscardLevel() + 1; } -void LLViewerFetchedTexture::setIsMissingAsset(bool is_missing) +void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing) { + if (is_missing == mIsMissingAsset) + { + return; + } if (is_missing) { if (mUrl.empty()) diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 1f2079104f..9465fe180b 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -120,7 +120,7 @@ public: LLViewerTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps) ; virtual S8 getType() const; - virtual BOOL isMissingAsset()const ; + virtual BOOL isMissingAsset() const ; virtual void dump(); // debug info to llinfos /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; @@ -338,8 +338,8 @@ public: // more data. /*virtual*/ void setKnownDrawSize(S32 width, S32 height); - void setIsMissingAsset(bool is_missing = true); - /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } + void setIsMissingAsset(BOOL is_missing = true); + /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } // returns dimensions of original image for local files (before power of two scaling) // and returns 0 for all asset system images @@ -449,7 +449,7 @@ protected: bool mCanUseHTTP ; //This texture can be fetched through http if true. FTType mFTType; // What category of image is this - map tile, server bake, etc? - mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. + mutable BOOL mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. typedef std::list callback_list_t; S8 mLoadedCallbackDesiredDiscardLevel; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index a71bb93ba2..58da77efbb 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1884,6 +1884,10 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU LL_DEBUGS("Avatar") << avString() << "from URL " << url << llendl; result = LLViewerTextureManager::getFetchedTextureFromUrl( url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); + if (result->isMissingAsset()) + { + result->setIsMissingAsset(false); + } } else { -- cgit v1.2.3 From 985b7277e824c39275d9a06c6262b6f394b02133 Mon Sep 17 00:00:00 2001 From: prep Date: Mon, 8 Apr 2013 17:10:46 -0400 Subject: WIP SH-4035: confirmation when closing appearance window when changes present --- indra/newview/llfloatersidepanelcontainer.cpp | 16 ++-- indra/newview/llfloatersidepanelcontainer.h | 2 + indra/newview/llinspectavatar.cpp | 5 +- indra/newview/llsidepanelappearance.cpp | 88 +++++++++++++++++++++- indra/newview/llsidepanelappearance.h | 16 +++- indra/newview/llspeakers.cpp | 5 +- .../newview/skins/default/xui/en/notifications.xml | 13 ++++ 7 files changed, 126 insertions(+), 19 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index 5f9556a870..b1f9a18d6f 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -67,15 +67,17 @@ void LLFloaterSidePanelContainer::onClickCloseBtn() if (parent == this ) { LLSidepanelAppearance* panel_appearance = dynamic_cast(getPanel("appearance")); - if ( panel_appearance ) - { - panel_appearance->getWearable()->onClose(); - panel_appearance->showOutfitsInventoryPanel(); - } + panel_appearance->onClose(this); } } - - LLFloater::onClickCloseBtn(); + else + { + LLFloater::onClickCloseBtn(); + } +} +void LLFloaterSidePanelContainer::close() +{ + LLFloater::onClickCloseBtn(); } LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_name, const LLSD& params) diff --git a/indra/newview/llfloatersidepanelcontainer.h b/indra/newview/llfloatersidepanelcontainer.h index 491723471f..940673b643 100644 --- a/indra/newview/llfloatersidepanelcontainer.h +++ b/indra/newview/llfloatersidepanelcontainer.h @@ -55,6 +55,8 @@ public: LLPanel* openChildPanel(const std::string& panel_name, const LLSD& params); + void close(); + static void showPanel(const std::string& floater_name, const LLSD& key); static void showPanel(const std::string& floater_name, const std::string& panel_name, const LLSD& key); diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 0b3268eb54..6ff16742dd 100644 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -292,10 +292,7 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data) delete mPropertiesRequest; mPropertiesRequest = NULL; } -/* -prep# - virtual void httpFailure() - */ + void LLInspectAvatar::updateVolumeSlider() { diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 74fa5a87bb..53b5593ac9 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -48,6 +48,8 @@ #include "llviewerregion.h" #include "llvoavatarself.h" #include "llviewerwearable.h" +#include "llnotificationsutil.h" +#include "llfloatersidepanelcontainer.h" static LLRegisterPanelClassWrapper t_appearance("sidepanel_appearance"); @@ -70,13 +72,84 @@ private: LLSidepanelAppearance *mPanel; }; +bool LLSidepanelAppearance::callBackExitWithoutSaveViaBack(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if ( option == 0 ) + { + gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE); + LLAppearanceMgr::instance().setOutfitDirty( true ); + showOutfitsInventoryPanel(); + LLAppearanceMgr::getInstance()->wearBaseOutfit(); + return true; + } + gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE); + return false; +} + +bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if ( option == 0 ) + { + gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE); + mEditWearable->revertChanges(); + LLAppearanceMgr::getInstance()->wearBaseOutfit(); + mLLFloaterSidePanelContainer->close(); + return true; + } + gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE); + return false; +} + +void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaClose() +{ + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + { + LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; + LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) ); + } + else + { + showOutfitsInventoryPanel(); + } +} + +void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack() +{ + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !mSidePanelJustOpened && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + { + LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; + LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaBack,pSelf,_1,_2) ); + } + else + { + showOutfitsInventoryPanel(); + } +} + +void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj) +{ + mLLFloaterSidePanelContainer = obj; + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + { + LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; + LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) ); + } + else + { + mLLFloaterSidePanelContainer->close(); + } +} + LLSidepanelAppearance::LLSidepanelAppearance() : LLPanel(), mFilterSubString(LLStringUtil::null), mFilterEditor(NULL), mOutfitEdit(NULL), mCurrOutfitPanel(NULL), - mOpened(false) + mOpened(false), + mSidePanelJustOpened(true) { LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); outfit_observer.addBOFReplacedCallback(boost::bind(&LLSidepanelAppearance::refreshCurrentOutfitName, this, "")); @@ -85,6 +158,8 @@ LLSidepanelAppearance::LLSidepanelAppearance() : gAgentWearables.addLoadingStartedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, true)); gAgentWearables.addLoadedCallback(boost::bind(&LLSidepanelAppearance::setWearablesLoading, this, false)); + + } LLSidepanelAppearance::~LLSidepanelAppearance() @@ -119,8 +194,8 @@ BOOL LLSidepanelAppearance::postBuild() { LLButton* back_btn = mOutfitEdit->getChild("back_btn"); if (back_btn) - { - back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::showOutfitsInventoryPanel, this)); + { + back_btn->setClickedCallback(boost::bind(&LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack, this)); } } @@ -144,6 +219,7 @@ BOOL LLSidepanelAppearance::postBuild() setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2)); + return TRUE; } @@ -183,6 +259,12 @@ void LLSidepanelAppearance::onOpen(const LLSD& key) void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility) { + //handle leaving and subsequent user verification of discarding any unsaved data + if ( mSidePanelJustOpened ) + { + mSidePanelJustOpened = false; + } + LLSD visibility; visibility["visible"] = new_visibility.asBoolean(); visibility["reset_accordion"] = false; diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 762f557a80..85e7734567 100644 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -38,9 +38,11 @@ class LLCurrentlyWornFetchObserver; class LLPanelEditWearable; class LLViewerWearable; class LLPanelOutfitsInventory; +class LLFloaterSidePanelContainer; class LLSidepanelAppearance : public LLPanel -{ +{ + LOG_CLASS(LLSidepanelAppearance); public: LLSidepanelAppearance(); @@ -48,6 +50,8 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); + void onClose(LLFloaterSidePanelContainer* obj); + void onClickCloseBtn(); void refreshCurrentOutfitName(const std::string& name = ""); @@ -65,6 +69,11 @@ public: void updateScrollingPanelList(); void updateToVisibility( const LLSD& new_visibility ); LLPanelEditWearable* getWearable(){ return mEditWearable; } + bool callBackExitWithoutSaveViaBack(const LLSD& notification, const LLSD& response); + void onClickConfirmExitWithoutSaveViaBack(); + bool callBackExitWithoutSaveViaClose(const LLSD& notification, const LLSD& response); + void onClickConfirmExitWithoutSaveViaClose(); + private: void onFilterEdit(const std::string& search_string); @@ -85,6 +94,7 @@ private: LLButton* mOpenOutfitBtn; LLButton* mEditAppearanceBtn; LLButton* mNewOutfitBtn; + LLPanel* mCurrOutfitPanel; LLTextBox* mCurrentLookName; @@ -99,6 +109,10 @@ private: // Gets set to true when we're opened for the first time. bool mOpened; + // Set to true if sidepanel has just been opened + bool mSidePanelJustOpened; + LLFloaterSidePanelContainer* mLLFloaterSidePanelContainer; + }; #endif //LL_LLSIDEPANELAPPEARANCE_H diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 3c3c699d17..bf209df863 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -855,10 +855,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) } } } -/*prep# - virtual void httpFailure() - llwarns << dumpResponse() << llendl; - */ + void LLIMSpeakerMgr::toggleAllowTextChat(const LLUUID& speaker_id) { LLPointer speakerp = findSpeaker(speaker_id); diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 105bef7321..2170283af2 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10030,5 +10030,18 @@ Cannot create large prims that intersect other players. Please re-try when othe name="okignore" yestext="OK"/> + + + + Closing this window will discard any changes you have made. + confirm + + -- cgit v1.2.3 From 4bbcd26941c3be6b83214d0dc45c70f99e474dda Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 8 Apr 2013 18:16:58 -0400 Subject: SH-4061 FIX - texture fetch failures added retry logic and fault injection for testing --- indra/newview/app_settings/settings.xml | 11 +++++++++++ indra/newview/lltexturefetch.cpp | 28 ++++++++++++++++++++-------- indra/newview/lltexturefetch.h | 2 +- indra/newview/llviewertexture.cpp | 29 ++++++++++++++++++++++------- indra/newview/llviewertexture.h | 1 + 5 files changed, 55 insertions(+), 16 deletions(-) mode change 100644 => 100755 indra/newview/lltexturefetch.h (limited to 'indra/newview') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f66d8fca5b..0b7f99ebc1 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11130,6 +11130,17 @@ Value 0 + TextureFetchFakeFailures + + Comment + Simulate HTTP fetch failures for some server bake textures. + Persist + 1 + Type + Boolean + Value + 0 + TextureFetchSource Comment diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index cc6dc64626..2e6fb160d5 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -388,10 +388,12 @@ public: // Threads: Ttf virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); + void setFakeFailure(bool fake_failure) { mFakeFailure = fake_failure; } + protected: LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, - F32 priority, S32 discard, S32 size); + F32 priority, S32 discard, S32 size, bool fake_failure); private: @@ -547,6 +549,7 @@ private: S32 mActiveCount; LLCore::HttpStatus mGetStatus; std::string mGetReason; + bool mFakeFailure; // Work Data LLMutex mWorkMutex; @@ -836,7 +839,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, const LLHost& host, // Simulator host F32 priority, // Priority S32 discard, // Desired discard - S32 size) // Desired size + S32 size, // Desired size + bool fake_failure) // For testing, simulate http failure if true. : LLWorkerClass(fetcher, "TextureFetch"), LLCore::HttpHandler(), mState(INIT), @@ -889,7 +893,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mHttpHasResource(false), mCacheReadCount(0U), mCacheWriteCount(0U), - mResourceWaitCount(0U) + mResourceWaitCount(0U), + mFakeFailure(fake_failure) { mCanUseNET = mUrl.empty() ; @@ -1519,15 +1524,16 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (http_not_found == mGetStatus) { + llwarns << "Texture missing from server (404): " << mUrl << llendl; + if(mWriteToCacheState == NOT_WRITE) //map tiles { setState(DONE); releaseHttpSemaphore(); - LL_DEBUGS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl; + LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl; return true; // failed, means no map tile on the empty region. } - llwarns << "Texture missing from server (404): " << mUrl << llendl; // roll back to try UDP if (mCanUseNET) @@ -1891,6 +1897,11 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); } + if (mFakeFailure) + { + llwarns << "For debugging, setting fake failure status for texture " << mID << llendl; + response->setStatus(LLCore::HttpStatus(404)); + } bool success = true; bool partial = false; LLCore::HttpStatus status(response->getStatus()); @@ -2455,7 +2466,7 @@ LLTextureFetch::~LLTextureFetch() } bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, - S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http) + S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http, bool fake_failure) { if(mFetcherLocked) { @@ -2523,7 +2534,8 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const worker->mNeedsAux = needs_aux; worker->setImagePriority(priority); worker->setDesiredDiscard(desired_discard, desired_size); - worker->setCanUseHTTP(can_use_http) ; + worker->setCanUseHTTP(can_use_http); + worker->setFakeFailure(fake_failure); if (!worker->haveWork()) { worker->setState(LLTextureFetchWorker::INIT); @@ -2538,7 +2550,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const } else { - worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size); + worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size, fake_failure); lockQueue(); // +Mfq mRequestMap[id] = worker; unlockQueue(); // -Mfq diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h old mode 100644 new mode 100755 index 902a3d7a25..b99480d18e --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -78,7 +78,7 @@ public: // Threads: T* (but Tmain mostly) bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, - S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http); + S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http, bool fake_failure); // Requests that a fetch operation be deleted from the queue. // If @cancel is true, also stops any I/O operations pending. diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 9cca8a244e..a157600cc9 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -962,6 +962,8 @@ void LLViewerFetchedTexture::init(bool firstinit) // does not contain this image. mIsMissingAsset = FALSE; + mFetchFailureCount = 0; + mLoadedCallbackDesiredDiscardLevel = S8_MAX; mPauseLoadedCallBacks = FALSE ; @@ -1823,12 +1825,18 @@ bool LLViewerFetchedTexture::updateFetch() // We finished but received no data if (current_discard < 0) { - llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority - << " mRawDiscardLevel " << mRawDiscardLevel - << " current_discard " << current_discard - << llendl; - setIsMissingAsset(); - desired_discard = -1; + const S32 MAX_FETCH_FAILURE = 1; + mFetchFailureCount++; + llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount << llendl; + if (getFTType() != FTT_SERVER_BAKE || mFetchFailureCount >= MAX_FETCH_FAILURE) + { + llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority + << " mRawDiscardLevel " << mRawDiscardLevel + << " current_discard " << current_discard + << llendl; + setIsMissingAsset(); + desired_discard = -1; + } } else { @@ -1942,8 +1950,14 @@ bool LLViewerFetchedTexture::updateFetch() // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; + bool fake_failure = false; + const bool debug_setting_fake_failures = gSavedSettings.getBOOL("TextureFetchFakeFailures"); + if (getFTType() == FTT_SERVER_BAKE && mFetchFailureCount == 0 && debug_setting_fake_failures) + { + fake_failure = true; + } fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority, - w, h, c, desired_discard, needsAux(), mCanUseHTTP); + w, h, c, desired_discard, needsAux(), mCanUseHTTP, fake_failure); if (fetch_request_created) { @@ -2040,6 +2054,7 @@ void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing) else { llinfos << mID << ": un-flagging missing asset" << llendl; + mFetchFailureCount = 0; } mIsMissingAsset = is_missing; } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 9465fe180b..320e6f8630 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -450,6 +450,7 @@ protected: FTType mFTType; // What category of image is this - map tile, server bake, etc? mutable BOOL mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. + S32 mFetchFailureCount; // How many times has a fetch failed in a way that suggests the asset is missing? typedef std::list callback_list_t; S8 mLoadedCallbackDesiredDiscardLevel; -- cgit v1.2.3 From 67790d0dd8fec2750906ae3d3fed1e735be6b078 Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Tue, 9 Apr 2013 15:14:51 -0500 Subject: SH-4035: Bug fix to handle closing the panel when editing a specific wearable --- indra/newview/llsidepanelappearance.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 53b5593ac9..3899450804 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -131,7 +131,9 @@ void LLSidepanelAppearance::onClickConfirmExitWithoutSaveViaBack() void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj) { mLLFloaterSidePanelContainer = obj; - if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && !LLAppearanceMgr::getInstance()->isOutfitLocked() ) + if ( LLAppearanceMgr::getInstance()->isOutfitDirty() && + !LLAppearanceMgr::getInstance()->isOutfitLocked() || + ( mEditWearable->isAvailable() && mEditWearable->isDirty() ) ) { LLSidepanelAppearance* pSelf = (LLSidepanelAppearance *)this; LLNotificationsUtil::add("ConfirmExitWithoutSave", LLSD(), LLSD(), boost::bind(&LLSidepanelAppearance::callBackExitWithoutSaveViaClose,pSelf,_1,_2) ); -- cgit v1.2.3 From 24fa7736dd123429425d91b2b72c3b3b7110b764 Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Tue, 9 Apr 2013 15:30:51 -0500 Subject: SH-4035: Removed unneeded functional call --- indra/newview/llsidepanelappearance.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 3899450804..ae6ceabdaa 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -93,7 +93,6 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica if ( option == 0 ) { gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE); - mEditWearable->revertChanges(); LLAppearanceMgr::getInstance()->wearBaseOutfit(); mLLFloaterSidePanelContainer->close(); return true; -- cgit v1.2.3 From f78da987913de659367b24e3aa0add2c570f8e1f Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 10 Apr 2013 11:43:48 -0400 Subject: SH-4061 WIP - capture http status codes from requests, restrict SB fetch retries to 5xx errors --- indra/newview/lltexturefetch.cpp | 15 ++++++++++----- indra/newview/lltexturefetch.h | 3 ++- indra/newview/llviewertexture.cpp | 20 ++++++++++++++++---- indra/newview/llviewertexture.h | 4 +++- 4 files changed, 31 insertions(+), 11 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 2e6fb160d5..5a6338d9d8 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -382,6 +382,8 @@ public: void setCanUseHTTP(bool can_use_http) { mCanUseHTTP = can_use_http; } bool getCanUseHTTP() const { return mCanUseHTTP; } + void setUrl(const std::string& url) { mUrl = url; } + LLTextureFetch & getFetcher() { return *mFetcher; } // Inherited from LLCore::HttpHandler @@ -1291,7 +1293,7 @@ bool LLTextureFetchWorker::doWork(S32 param) std::string http_url = region->getHttpUrl() ; if (!http_url.empty()) { - mUrl = http_url + "/?texture_id=" + mID.asString().c_str(); + setUrl(http_url + "/?texture_id=" + mID.asString().c_str()); mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id. } else @@ -1900,7 +1902,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe if (mFakeFailure) { llwarns << "For debugging, setting fake failure status for texture " << mID << llendl; - response->setStatus(LLCore::HttpStatus(404)); + response->setStatus(LLCore::HttpStatus(500)); } bool success = true; bool partial = false; @@ -1918,11 +1920,11 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe // << " offset: " << offset << " length: " << length // << llendl; + std::string reason(status.toString()); + setGetStatus(status, reason); if (! status) { success = false; - std::string reason(status.toString()); - setGetStatus(status, reason); llwarns << "CURL GET FAILED, status: " << status.toHex() << " reason: " << reason << llendl; } @@ -2535,6 +2537,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const worker->setImagePriority(priority); worker->setDesiredDiscard(desired_discard, desired_size); worker->setCanUseHTTP(can_use_http); + worker->setUrl(url); worker->setFakeFailure(fake_failure); if (!worker->haveWork()) { @@ -2741,7 +2744,8 @@ LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id) // Threads: T* bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, - LLPointer& raw, LLPointer& aux) + LLPointer& raw, LLPointer& aux, + LLCore::HttpStatus& last_http_get_status) { bool res = false; LLTextureFetchWorker* worker = getWorker(id); @@ -2763,6 +2767,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, else if (worker->checkWork()) { worker->lockWorkMutex(); // +Mw + last_http_get_status = worker->mGetStatus; discard_level = worker->mDecodedDiscard; raw = worker->mRawImage; aux = worker->mAuxImage; diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index b99480d18e..9f77d58727 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -95,7 +95,8 @@ public: // Threads: T* bool getRequestFinished(const LLUUID& id, S32& discard_level, - LLPointer& raw, LLPointer& aux); + LLPointer& raw, LLPointer& aux, + LLCore::HttpStatus& last_http_get_status); // Threads: T* bool updateRequestPriority(const LLUUID& id, F32 priority); diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index a157600cc9..7a1afb1238 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1760,7 +1760,8 @@ bool LLViewerFetchedTexture::updateFetch() if (mRawImage.notNull()) sRawCount--; if (mAuxRawImage.notNull()) sAuxCount--; - bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage); + bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage, + mLastHttpGetStatus); if (mRawImage.notNull()) sRawCount++; if (mAuxRawImage.notNull()) sAuxCount++; if (finished) @@ -1825,14 +1826,25 @@ bool LLViewerFetchedTexture::updateFetch() // We finished but received no data if (current_discard < 0) { - const S32 MAX_FETCH_FAILURE = 1; + const S32 MAX_FETCH_FAILURE = 3; mFetchFailureCount++; - llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount << llendl; - if (getFTType() != FTT_SERVER_BAKE || mFetchFailureCount >= MAX_FETCH_FAILURE) + llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount + << " status " << mLastHttpGetStatus.toHex() << llendl; + // Will retry server-bake textures under a limited set of circumstances. + if (getFTType() == FTT_SERVER_BAKE && + mLastHttpGetStatus.isHttpStatus() && + mLastHttpGetStatus.mType >= 500 && + mLastHttpGetStatus.mType <= 599 && // Only retry 5xx failures. + mFetchFailureCount < MAX_FETCH_FAILURE) + { + llwarns << "Will retry fetch" << llendl; + } + else // Otherwise, assume the image is missing. { llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority << " mRawDiscardLevel " << mRawDiscardLevel << " current_discard " << current_discard + << " stats " << mLastHttpGetStatus.toHex() << llendl; setIsMissingAsset(); desired_discard = -1; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 320e6f8630..91e903ffd6 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -34,6 +34,7 @@ #include "llgltypes.h" #include "llrender.h" #include "llmetricperformancetester.h" +#include "httpcommon.h" #include #include @@ -446,7 +447,8 @@ protected: S8 mIsRawImageValid; S8 mHasFetcher; // We've made a fecth request S8 mIsFetching; // Fetch request is active - bool mCanUseHTTP ; //This texture can be fetched through http if true. + bool mCanUseHTTP; //This texture can be fetched through http if true. + LLCore::HttpStatus mLastHttpGetStatus; // Result of the most recently completed http request for this texture. FTType mFTType; // What category of image is this - map tile, server bake, etc? mutable BOOL mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. -- cgit v1.2.3 From 34e2478388341a1add33bf88cac43031e351340e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 10 Apr 2013 11:57:22 -0400 Subject: SH-4061 WIP - less log spamming for (expected and normal) map tile failures. --- indra/newview/lltexturefetch.cpp | 21 +++++++++++++++------ indra/newview/llviewertexture.cpp | 20 +++++++++++++------- 2 files changed, 28 insertions(+), 13 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 5a6338d9d8..58cfc80839 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1526,14 +1526,20 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (http_not_found == mGetStatus) { - llwarns << "Texture missing from server (404): " << mUrl << llendl; + if (mFTType != FTT_MAP_TILE) + { + llwarns << "Texture missing from server (404): " << mUrl << llendl; + } - if(mWriteToCacheState == NOT_WRITE) //map tiles + if(mWriteToCacheState == NOT_WRITE) //map tiles or server bakes { setState(DONE); releaseHttpSemaphore(); - LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl; - return true; // failed, means no map tile on the empty region. + if (mFTType != FTT_MAP_TILE) + { + LL_WARNS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << llendl; + } + return true; } @@ -1925,8 +1931,11 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe if (! status) { success = false; - llwarns << "CURL GET FAILED, status: " << status.toHex() - << " reason: " << reason << llendl; + if (mFTType != FTT_MAP_TILE) // missing map tiles are normal, don't complain about them. + { + llwarns << "CURL GET FAILED, status: " << status.toHex() + << " reason: " << reason << llendl; + } } else { diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 7a1afb1238..5f4c66a04c 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1828,8 +1828,11 @@ bool LLViewerFetchedTexture::updateFetch() { const S32 MAX_FETCH_FAILURE = 3; mFetchFailureCount++; - llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount - << " status " << mLastHttpGetStatus.toHex() << llendl; + if (getFTType() != FTT_MAP_TILE) + { + llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount + << " status " << mLastHttpGetStatus.toHex() << llendl; + } // Will retry server-bake textures under a limited set of circumstances. if (getFTType() == FTT_SERVER_BAKE && mLastHttpGetStatus.isHttpStatus() && @@ -1841,11 +1844,14 @@ bool LLViewerFetchedTexture::updateFetch() } else // Otherwise, assume the image is missing. { - llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority - << " mRawDiscardLevel " << mRawDiscardLevel - << " current_discard " << current_discard - << " stats " << mLastHttpGetStatus.toHex() - << llendl; + if (getFTType() != FTT_MAP_TILE) + { + llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority + << " mRawDiscardLevel " << mRawDiscardLevel + << " current_discard " << current_discard + << " stats " << mLastHttpGetStatus.toHex() + << llendl; + } setIsMissingAsset(); desired_discard = -1; } -- cgit v1.2.3 From 2798c355c441f8d92a02537eca6e253c8fbf2bc4 Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Wed, 10 Apr 2013 16:53:46 -0500 Subject: SH-4035:Added ignore message to notification --- indra/newview/llsidepanelappearance.cpp | 6 +----- indra/newview/skins/default/xui/en/notifications.xml | 7 ++++--- 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index ae6ceabdaa..6d2b643434 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -77,13 +77,11 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaBack(const LLSD& notificat S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) { - gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE); LLAppearanceMgr::instance().setOutfitDirty( true ); showOutfitsInventoryPanel(); LLAppearanceMgr::getInstance()->wearBaseOutfit(); return true; } - gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE); return false; } @@ -91,13 +89,11 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica { S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) - { - gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", TRUE); + { LLAppearanceMgr::getInstance()->wearBaseOutfit(); mLLFloaterSidePanelContainer->close(); return true; } - gSavedSettings.setBOOL("ExitOutfitEditWithoutSave", FALSE); return false; } diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 2170283af2..1ff63c6def 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -10039,9 +10039,10 @@ Cannot create large prims that intersect other players. Please re-try when othe Closing this window will discard any changes you have made. confirm + yestext="OK" + ignoretext="Don't show me this again."/> - + -- cgit v1.2.3 From 14ca6a1247e68805aae22cf573a39819383fe3d4 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 11 Apr 2013 11:18:16 -0400 Subject: SH-4061 WIP - moved retry policy to llmessage, added integration test --- indra/newview/llappearancemgr.cpp | 79 +++------------------------------------ 1 file changed, 5 insertions(+), 74 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index c2be472cbc..85f6f92278 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -52,6 +52,7 @@ #include "llwearablelist.h" #include "llsdutil.h" #include "llsdserialize.h" +#include "llhttpretrypolicy.h" #if LL_MSVC // disable boost::lexical_cast warning @@ -2957,78 +2958,6 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base if (inventory_changed) gInventory.notifyObservers(); } -// This is intended for use with HTTP Clients/Responders, but is not -// specifically coupled with those classes. -class LLHTTPRetryPolicy: public LLThreadSafeRefCount -{ -public: - LLHTTPRetryPolicy() {} - virtual ~LLHTTPRetryPolicy() {} - virtual bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) = 0; -}; - -// Example of simplest possible policy, not necessarily recommended. -// This would be a potentially dangerous policy to enable. Removing for now: -#if 0 -class LLAlwaysRetryImmediatelyPolicy: public LLHTTPRetryPolicy -{ -public: - LLAlwaysRetryImmediatelyPolicy() {} - bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) - { - seconds_to_wait = 0.0; - return true; - } -}; -#endif - -// Very general policy with geometric back-off after failures, -// up to a maximum delay, and maximum number of retries. -class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy -{ -public: - LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries): - mMinDelay(min_delay), - mMaxDelay(max_delay), - mBackoffFactor(backoff_factor), - mMaxRetries(max_retries), - mDelay(min_delay), - mRetryCount(0) - { - } - - bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) - { -#if 0 - // *TODO: Test using status codes to only retry server errors. - // Only server errors would potentially return a different result on retry. - if (!isHttpServerErrorStatus(status)) return false; -#endif - -#if 0 - // *TODO: Honor server Retry-After header. - // Status 503 may ask us to wait for a certain amount of time before retrying. - if (!headers.has(HTTP_IN_HEADER_RETRY_AFTER) - || !getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait)) -#endif - { - seconds_to_wait = mDelay; - mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); - } - - mRetryCount++; - return (mRetryCount<=mMaxRetries); - } - -private: - F32 mMinDelay; // delay never less than this value - F32 mMaxDelay; // delay never exceeds this value - F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay. - U32 mMaxRetries; // maximum number of times shouldRetry will return true. - F32 mDelay; // current delay. - U32 mRetryCount; // number of times shouldRetry has been called. -}; - class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder { LOG_CLASS(RequestAgentUpdateAppearanceResponder); @@ -3084,7 +3013,8 @@ protected: void onFailure() { F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait)) + mRetryPolicy->onFailure(getStatus(), getResponseHeaders()); + if (mRetryPolicy->shouldRetry(seconds_to_wait)) { llinfos << "retrying" << llendl; doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate, @@ -3327,7 +3257,8 @@ protected: LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error " << dumpResponse() << LL_ENDL; F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait)) + mRetryPolicy->onFailure(getStatus(), getResponseHeaders()); + if (mRetryPolicy->shouldRetry(seconds_to_wait)) { llinfos << "retrying" << llendl; doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion, -- cgit v1.2.3 From e17920defbf1d39ecd9e88500ba268c59bb84008 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 11 Apr 2013 16:17:23 -0400 Subject: SH-4061 WIP - started adding retry to texture fetch, making retry policy compatible with old and new http libraries --- indra/newview/lltexturefetch.cpp | 1 + indra/newview/lltexturefetch.h | 3 +++ 2 files changed, 4 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 58cfc80839..026f36e205 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1918,6 +1918,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe << " status: " << status.toHex() << " '" << status.toString() << "'" << llendl; + // unsigned int offset(0), length(0), full_length(0); // response->getRange(&offset, &length, &full_length); // llwarns << "HTTP COMPLETE: " << mID << " handle: " << handle diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 9f77d58727..c6bd342a7b 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -396,6 +396,9 @@ private: e_tex_source mFetchSource; e_tex_source mOriginFetchSource; + // Retry logic + LLAdaptiveRetryPolicy mFetchRetryPolicy; + public: //debug use LLTextureFetchDebugger* getFetchDebugger() { return mFetchDebugger;} -- cgit v1.2.3 From a8cdcfc9a893b7debf7c006022b57c389b50bf0d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 12 Apr 2013 09:16:25 -0400 Subject: SH-4061 WIP - moved retry policy to newview so it can work with either llmessage or CoreHttp libraries. Updated tests. --- indra/newview/CMakeLists.txt | 5 + indra/newview/llhttpretrypolicy.cpp | 117 +++++++++++ indra/newview/llhttpretrypolicy.h | 94 +++++++++ indra/newview/lltexturefetch.h | 2 +- indra/newview/tests/llhttpretrypolicy_test.cpp | 275 +++++++++++++++++++++++++ 5 files changed, 492 insertions(+), 1 deletion(-) mode change 100644 => 100755 indra/newview/CMakeLists.txt create mode 100755 indra/newview/llhttpretrypolicy.cpp create mode 100755 indra/newview/llhttpretrypolicy.h create mode 100755 indra/newview/tests/llhttpretrypolicy_test.cpp (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt old mode 100644 new mode 100755 index 05736f6360..27dbe15005 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -299,6 +299,7 @@ set(viewer_SOURCE_FILES llgroupmgr.cpp llhints.cpp llhomelocationresponder.cpp + llhttpretrypolicy.cpp llhudeffect.cpp llhudeffectbeam.cpp llhudeffectlookat.cpp @@ -877,6 +878,7 @@ set(viewer_HEADER_FILES llgrouplist.h llgroupmgr.h llhints.h + llhttpretrypolicy.h llhomelocationresponder.h llhudeffect.h llhudeffectbeam.h @@ -2152,6 +2154,7 @@ if (LL_TESTS) set(test_libs ${LLMESSAGE_LIBRARIES} + ${LLCOREHTTP_LIBRARIES} ${WINDOWS_LIBRARIES} ${LLVFS_LIBRARIES} ${LLMATH_LIBRARIES} @@ -2197,6 +2200,8 @@ if (LL_TESTS) "${test_libs}" ) + LL_ADD_INTEGRATION_TEST(llhttpretrypolicy "llhttpretrypolicy.cpp" "${test_libs}") + #ADD_VIEWER_BUILD_TEST(llmemoryview viewer) #ADD_VIEWER_BUILD_TEST(llagentaccess viewer) #ADD_VIEWER_BUILD_TEST(lltextureinfo viewer) diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp new file mode 100755 index 0000000000..5c6dabbe99 --- /dev/null +++ b/indra/newview/llhttpretrypolicy.cpp @@ -0,0 +1,117 @@ +/** + * @file llhttpretrypolicy.h + * @brief Header for a retry policy class intended for use with http responders. + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llhttpretrypolicy.h" + +bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time) +{ + return (headers.has(HTTP_IN_HEADER_RETRY_AFTER) + && getSecondsUntilRetryAfter(headers[HTTP_IN_HEADER_RETRY_AFTER].asStringRef(), retry_header_time)); +} + +bool LLAdaptiveRetryPolicy::getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time) +{ + // Look for matching header. Hopefully it's correct enough to let + // us extract the field we are looking for. Does not purport to be + // in any way a viable general HTTP header parser. + if (headers) + { + for (std::vector::const_iterator it = headers->mHeaders.begin(); + it != headers->mHeaders.end(); + ++it) + { + const std::string& str = *it; + const std::string match = HTTP_IN_HEADER_RETRY_AFTER + ":"; + size_t pos = str.find(match); + if ((pos != std::string::npos) && + (pos+match.length() <= str.length())) + { + retry_header_time = strtod(str.substr(pos+match.length()).c_str(), NULL); + return true; + } + } + } + return false; +} + +void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers) +{ + F32 retry_header_time; + bool has_retry_header_time = getRetryAfter(headers,retry_header_time); + onFailureCommon(status, has_retry_header_time, retry_header_time); +} + +// TODO: replace this parsing junk once CoreHttp has its own header parsing capabilities. +void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response) +{ + F32 retry_header_time; + const LLCore::HttpHeaders *headers = response->getHeaders(); + bool has_retry_header_time = getRetryAfter(headers,retry_header_time); + onFailureCommon(response->getStatus().mType, has_retry_header_time, retry_header_time); +} + +void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time) +{ + if (mRetryCount > 0) + { + mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); + } + // Honor server Retry-After header. + // Status 503 may ask us to wait for a certain amount of time before retrying. + F32 wait_time = mDelay; + if (has_retry_header_time) + { + wait_time = retry_header_time; + } + + if (mRetryCount>=mMaxRetries) + { + llinfos << "Too many retries " << mRetryCount << ", will not retry" << llendl; + mShouldRetry = false; + } + if (!isHttpServerErrorStatus(status)) + { + llinfos << "Non-server error " << status << ", will not retry" << llendl; + mShouldRetry = false; + } + if (mShouldRetry) + { + llinfos << "Retry count " << mRetryCount << " should retry after " << wait_time << llendl; + mRetryTimer.reset(); + mRetryTimer.setTimerExpirySec(wait_time); + } + mRetryCount++; +} + + +bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const +{ + llassert(mRetryCount>0); // have to call onFailure() before shouldRetry() + seconds_to_wait = mShouldRetry ? mRetryTimer.getRemainingTimeF32() : F32_MAX; + return mShouldRetry; +} diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h new file mode 100755 index 0000000000..ca37e5f73c --- /dev/null +++ b/indra/newview/llhttpretrypolicy.h @@ -0,0 +1,94 @@ +/** + * @file file llhttpretrypolicy.h + * @brief declarations for http retry policy class. + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_RETRYPOLICY_H +#define LL_RETRYPOLICY_H + +#include "lltimer.h" +#include "llthread.h" + +#include "llhttpconstants.h" + +// For compatibility with new core http lib. +#include "httpresponse.h" +#include "httpheaders.h" + +// This is intended for use with HTTP Clients/Responders, but is not +// specifically coupled with those classes. +class LLHTTPRetryPolicy: public LLThreadSafeRefCount +{ +public: + LLHTTPRetryPolicy() {} + virtual ~LLHTTPRetryPolicy() {} + // Call once after an HTTP failure to update state. + virtual void onFailure(S32 status, const LLSD& headers) = 0; + + virtual void onFailure(const LLCore::HttpResponse *response) = 0; + + virtual bool shouldRetry(F32& seconds_to_wait) const = 0; +}; + +// Very general policy with geometric back-off after failures, +// up to a maximum delay, and maximum number of retries. +class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy +{ +public: + LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries): + mMinDelay(min_delay), + mMaxDelay(max_delay), + mBackoffFactor(backoff_factor), + mMaxRetries(max_retries), + mDelay(min_delay), + mRetryCount(0), + mShouldRetry(true) + { + } + + // virtual + void onFailure(S32 status, const LLSD& headers); + // virtual + void onFailure(const LLCore::HttpResponse *response); + // virtual + bool shouldRetry(F32& seconds_to_wait) const; + +protected: + bool getRetryAfter(const LLSD& headers, F32& retry_header_time); + bool getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time); + void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time); + +private: + + F32 mMinDelay; // delay never less than this value + F32 mMaxDelay; // delay never exceeds this value + F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay. + U32 mMaxRetries; // maximum number of times shouldRetry will return true. + F32 mDelay; // current default delay. + U32 mRetryCount; // number of times shouldRetry has been called. + LLTimer mRetryTimer; // time until next retry. + bool mShouldRetry; // Becomes false after too many retries, or the wrong sort of status received, etc. +}; + +#endif diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index c6bd342a7b..12226d51c8 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -397,7 +397,7 @@ private: e_tex_source mOriginFetchSource; // Retry logic - LLAdaptiveRetryPolicy mFetchRetryPolicy; + //LLAdaptiveRetryPolicy mFetchRetryPolicy; public: //debug use diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp new file mode 100755 index 0000000000..39bd15d62f --- /dev/null +++ b/indra/newview/tests/llhttpretrypolicy_test.cpp @@ -0,0 +1,275 @@ +/** + * @file llhttpretrypolicy_test.cpp + * @brief Header tests to exercise the LLHTTPRetryPolicy classes. + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "../llviewerprecompiledheaders.h" +#include "../llhttpretrypolicy.h" +#include "lltut.h" + +namespace tut +{ +struct TestData +{ +}; + +typedef test_group RetryPolicyTestGroup; +typedef RetryPolicyTestGroup::object RetryPolicyTestObject; +RetryPolicyTestGroup retryPolicyTestGroup("retry_policy"); + +template<> template<> +void RetryPolicyTestObject::test<1>() +{ + LLAdaptiveRetryPolicy never_retry(1.0,1.0,1.0,0); + LLSD headers; + F32 wait_seconds; + + never_retry.onFailure(500,headers); + ensure("never retry", !never_retry.shouldRetry(wait_seconds)); +} + +template<> template<> +void RetryPolicyTestObject::test<2>() +{ + LLAdaptiveRetryPolicy retry404(1.0,2.0,3.0,10); + LLSD headers; + F32 wait_seconds; + + retry404.onFailure(404,headers); + ensure("no retry on 404", !retry404.shouldRetry(wait_seconds)); +} + +template<> template<> +void RetryPolicyTestObject::test<3>() +{ + // Should retry after 1.0, 2.0, 3.0, 3.0 seconds. + LLAdaptiveRetryPolicy basic_retry(1.0,3.0,2.0,4); + LLSD headers; + F32 wait_seconds; + bool should_retry; + U32 frac_bits = 6; + + // Starting wait 1.0 + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 1", should_retry); + ensure_approximately_equals("basic_retry 1", wait_seconds, 1.0F, frac_bits); + + // Double wait to 2.0 + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 2", should_retry); + ensure_approximately_equals("basic_retry 2", wait_seconds, 2.0F, frac_bits); + + // Hit max wait of 3.0 (4.0 clamped to max 3) + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 3", should_retry); + ensure_approximately_equals("basic_retry 3", wait_seconds, 3.0F, frac_bits); + + // At max wait, should stay at 3.0 + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 4", should_retry); + ensure_approximately_equals("basic_retry 4", wait_seconds, 3.0F, frac_bits); + + // Max retries, should fail now. + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 5", !should_retry); +} + +// Retries should stop as soon as a non-5xx error is received. +template<> template<> +void RetryPolicyTestObject::test<4>() +{ + // Should retry after 1.0, 2.0, 3.0, 3.0 seconds. + LLAdaptiveRetryPolicy killer404(1.0,3.0,2.0,4); + LLSD headers; + F32 wait_seconds; + bool should_retry; + U32 frac_bits = 6; + + // Starting wait 1.0 + killer404.onFailure(500,headers); + should_retry = killer404.shouldRetry(wait_seconds); + ensure("killer404 1", should_retry); + ensure_approximately_equals("killer404 1", wait_seconds, 1.0F, frac_bits); + + // Double wait to 2.0 + killer404.onFailure(500,headers); + should_retry = killer404.shouldRetry(wait_seconds); + ensure("killer404 2", should_retry); + ensure_approximately_equals("killer404 2", wait_seconds, 2.0F, frac_bits); + + // Should fail on non-5xx + killer404.onFailure(404,headers); + should_retry = killer404.shouldRetry(wait_seconds); + ensure("killer404 3", !should_retry); + + // After a non-5xx, should keep failing. + killer404.onFailure(500,headers); + should_retry = killer404.shouldRetry(wait_seconds); + ensure("killer404 4", !should_retry); +} + +// Test handling of "retry-after" header. If present, this header +// value overrides the computed delay, but does not affect the +// progression of delay values. For example, if the normal +// progression of delays would be 1,2,4,8..., but the 2nd and 3rd calls +// get a retry header of 33, the pattern would become 1,33,33,8... +template<> template<> +void RetryPolicyTestObject::test<5>() +{ + LLAdaptiveRetryPolicy policy(1.0,25.0,2.0,6); + LLSD headers_with_retry; + headers_with_retry[HTTP_IN_HEADER_RETRY_AFTER] = "666"; + LLSD headers_without_retry; + F32 wait_seconds; + bool should_retry; + U32 frac_bits = 6; + + policy.onFailure(500,headers_without_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 1", should_retry); + ensure_approximately_equals("retry header 1", wait_seconds, 1.0F, frac_bits); + + policy.onFailure(500,headers_without_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 2", should_retry); + ensure_approximately_equals("retry header 2", wait_seconds, 2.0F, frac_bits); + + policy.onFailure(500,headers_with_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 3", should_retry); + // 4.0 overrides by header -> 666.0 + ensure_approximately_equals("retry header 3", wait_seconds, 666.0F, frac_bits); + + policy.onFailure(500,headers_with_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 4", should_retry); + // 8.0 overrides by header -> 666.0 + ensure_approximately_equals("retry header 4", wait_seconds, 666.0F, frac_bits); + + policy.onFailure(500,headers_without_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 5", should_retry); + ensure_approximately_equals("retry header 5", wait_seconds, 16.0F, frac_bits); + + policy.onFailure(500,headers_without_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 6", should_retry); + ensure_approximately_equals("retry header 6", wait_seconds, 25.0F, frac_bits); + + policy.onFailure(500,headers_with_retry); + should_retry = policy.shouldRetry(wait_seconds); + ensure("retry header 7", !should_retry); +} + +// Test getSecondsUntilRetryAfter(const std::string& retry_after, F32& seconds_to_wait), +// used by header parsing of the retry policy. +template<> template<> +void RetryPolicyTestObject::test<6>() +{ + F32 seconds_to_wait; + bool success; + + std::string str1("0"); + seconds_to_wait = F32_MAX; + success = getSecondsUntilRetryAfter(str1, seconds_to_wait); + ensure("parse 1", success); + ensure_equals("parse 1", seconds_to_wait, 0.0); + + std::string str2("999.9"); + seconds_to_wait = F32_MAX; + success = getSecondsUntilRetryAfter(str2, seconds_to_wait); + ensure("parse 2", success); + ensure_approximately_equals("parse 2", seconds_to_wait, 999.9F, 8); + + time_t nowseconds; + time(&nowseconds); + std::string str3 = LLDate((F64)nowseconds).asRFC1123(); + seconds_to_wait = F32_MAX; + success = getSecondsUntilRetryAfter(str3, seconds_to_wait); + ensure("parse 3", success); + ensure_approximately_equals("parse 3", seconds_to_wait, 0.0F, 6); +} + +// Test retry-after field in both llmessage and CoreHttp headers. +template<> template<> +void RetryPolicyTestObject::test<7>() +{ + LLSD sd_headers; + time_t nowseconds; + time(&nowseconds); + sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = LLDate((F64)nowseconds).asRFC1123(); + LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,10); + F32 seconds_to_wait; + bool should_retry; + + // no retry header, use default. + policy.onFailure(500,LLSD()); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 1", should_retry); + ensure_approximately_equals("header 1", seconds_to_wait, 17.0F, 6); + + // retry header should override, give delay of 0 + policy.onFailure(503,sd_headers); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 2", should_retry); + ensure_approximately_equals("header 2", seconds_to_wait, 0.0F, 6); + + // retry header in LLCore::HttpHeaders + { + LLCore::HttpResponse *response = new LLCore::HttpResponse(); + LLCore::HttpHeaders *headers = new LLCore::HttpHeaders(); + response->setStatus(503); + response->setHeaders(headers); + headers->mHeaders.push_back("retry-after: 600"); + policy.onFailure(response); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 3",should_retry); + ensure_approximately_equals("header 3", seconds_to_wait, 600.0F, 6); + response->release(); + } + + // retry header in LLCore::HttpHeaders + { + LLCore::HttpResponse *response = new LLCore::HttpResponse(); + LLCore::HttpHeaders *headers = new LLCore::HttpHeaders(); + response->setStatus(503); + response->setHeaders(headers); + LLSD sd_headers; + time(&nowseconds); + headers->mHeaders.push_back("retry-after: " + LLDate((F64)nowseconds).asRFC1123()); + policy.onFailure(response); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 3",should_retry); + ensure_approximately_equals("header 3", seconds_to_wait, 0.0F, 6); + response->release(); + } +} + +} + -- cgit v1.2.3 From 766daa73a29d34cb3410c033fc99bfc156844c92 Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Fri, 12 Apr 2013 10:09:44 -0500 Subject: Sh-4035: Fix for skin changes not being reverted after cancel --- indra/newview/llsidepanelappearance.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 6d2b643434..7b89e0617b 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -90,6 +90,7 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) { + mEditWearable->revertChanges(); LLAppearanceMgr::getInstance()->wearBaseOutfit(); mLLFloaterSidePanelContainer->close(); return true; -- cgit v1.2.3 From bb237ce15f0a7bc4a3fbffc45b1e4548fd1d2f81 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Fri, 12 Apr 2013 17:04:48 -0400 Subject: SH_4061 WIP - retry policy org and tests --- indra/newview/llhttpretrypolicy.cpp | 23 +++++++++++++++++- indra/newview/llhttpretrypolicy.h | 11 +-------- indra/newview/tests/llhttpretrypolicy_test.cpp | 33 +++++++++++++++++++++----- 3 files changed, 50 insertions(+), 17 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp index 5c6dabbe99..82f6eab00e 100755 --- a/indra/newview/llhttpretrypolicy.cpp +++ b/indra/newview/llhttpretrypolicy.cpp @@ -28,6 +28,17 @@ #include "llhttpretrypolicy.h" +LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries): + mMinDelay(min_delay), + mMaxDelay(max_delay), + mBackoffFactor(backoff_factor), + mMaxRetries(max_retries), + mDelay(min_delay), + mRetryCount(0), + mShouldRetry(true) +{ +} + bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time) { return (headers.has(HTTP_IN_HEADER_RETRY_AFTER) @@ -77,6 +88,11 @@ void LLAdaptiveRetryPolicy::onFailure(const LLCore::HttpResponse *response) void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time) { + if (!mShouldRetry) + { + llinfos << "keep on failing" << llendl; + return; + } if (mRetryCount > 0) { mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); @@ -111,7 +127,12 @@ void LLAdaptiveRetryPolicy::onFailureCommon(S32 status, bool has_retry_header_ti bool LLAdaptiveRetryPolicy::shouldRetry(F32& seconds_to_wait) const { - llassert(mRetryCount>0); // have to call onFailure() before shouldRetry() + if (mRetryCount == 0) + { + // Called shouldRetry before any failure. + seconds_to_wait = F32_MAX; + return false; + } seconds_to_wait = mShouldRetry ? mRetryTimer.getRemainingTimeF32() : F32_MAX; return mShouldRetry; } diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h index ca37e5f73c..6f63f047de 100755 --- a/indra/newview/llhttpretrypolicy.h +++ b/indra/newview/llhttpretrypolicy.h @@ -56,16 +56,7 @@ public: class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy { public: - LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries): - mMinDelay(min_delay), - mMaxDelay(max_delay), - mBackoffFactor(backoff_factor), - mMaxRetries(max_retries), - mDelay(min_delay), - mRetryCount(0), - mShouldRetry(true) - { - } + LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries); // virtual void onFailure(S32 status, const LLSD& headers); diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp index 39bd15d62f..43fc1178cc 100755 --- a/indra/newview/tests/llhttpretrypolicy_test.cpp +++ b/indra/newview/tests/llhttpretrypolicy_test.cpp @@ -45,8 +45,12 @@ void RetryPolicyTestObject::test<1>() LLSD headers; F32 wait_seconds; + // No retry until we've finished a try. + ensure("never retry 0", !never_retry.shouldRetry(wait_seconds)); + + // 0 retries max. never_retry.onFailure(500,headers); - ensure("never retry", !never_retry.shouldRetry(wait_seconds)); + ensure("never retry 1", !never_retry.shouldRetry(wait_seconds)); } template<> template<> @@ -70,6 +74,9 @@ void RetryPolicyTestObject::test<3>() bool should_retry; U32 frac_bits = 6; + // No retry until we've finished a try. + ensure("basic_retry 0", !basic_retry.shouldRetry(wait_seconds)); + // Starting wait 1.0 basic_retry.onFailure(500,headers); should_retry = basic_retry.shouldRetry(wait_seconds); @@ -224,10 +231,13 @@ void RetryPolicyTestObject::test<7>() time_t nowseconds; time(&nowseconds); sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = LLDate((F64)nowseconds).asRFC1123(); - LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,10); + LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,5); F32 seconds_to_wait; bool should_retry; + // No retry until we've finished a try. + ensure("header 0", !policy.shouldRetry(seconds_to_wait)); + // no retry header, use default. policy.onFailure(500,LLSD()); should_retry = policy.shouldRetry(seconds_to_wait); @@ -246,7 +256,7 @@ void RetryPolicyTestObject::test<7>() LLCore::HttpHeaders *headers = new LLCore::HttpHeaders(); response->setStatus(503); response->setHeaders(headers); - headers->mHeaders.push_back("retry-after: 600"); + headers->mHeaders.push_back(HTTP_IN_HEADER_RETRY_AFTER + ": 600"); policy.onFailure(response); should_retry = policy.shouldRetry(seconds_to_wait); ensure("header 3",should_retry); @@ -262,13 +272,24 @@ void RetryPolicyTestObject::test<7>() response->setHeaders(headers); LLSD sd_headers; time(&nowseconds); - headers->mHeaders.push_back("retry-after: " + LLDate((F64)nowseconds).asRFC1123()); + headers->mHeaders.push_back(HTTP_IN_HEADER_RETRY_AFTER + ": " + LLDate((F64)nowseconds).asRFC1123()); policy.onFailure(response); should_retry = policy.shouldRetry(seconds_to_wait); - ensure("header 3",should_retry); - ensure_approximately_equals("header 3", seconds_to_wait, 0.0F, 6); + ensure("header 4",should_retry); + ensure_approximately_equals("header 4", seconds_to_wait, 0.0F, 6); response->release(); } + + // Timeout should be clamped at max. + policy.onFailure(500,LLSD()); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 5", should_retry); + ensure_approximately_equals("header 5", seconds_to_wait, 644.0F, 6); + + // No more retries. + policy.onFailure(500,LLSD()); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 6", !should_retry); } } -- cgit v1.2.3 From 8868964b549822f260694c2bf26b903dbce8ed0a Mon Sep 17 00:00:00 2001 From: Monty Brandenberg Date: Mon, 15 Apr 2013 16:55:35 +0000 Subject: SH-4106 Significantly upgrade the HttpHeaders interface for SSB. Header container moves from a vector of raw lines to a vector of string pairs representing name/value pairs in headers. For incoming headers, we normalize the name to lowercase and trim it. Values are only left-trimmed. Outgoing headers are left as-is. Simple find() method for the common case, forward and reverse iterators for those few who need to do it themselves. The HTTP status line (e.g. 'HTTP/1.1 200 Ok') is no longer treated as a header to be returned to caller. Unit tests, as usual, were a bear but they absolutely ensured outgoing HTTP header conformance after the change. Grunt work paid off. LLTextureFetch was also given a second options structure for texture fetches. Same as the original but with header return to caller requested. Baked textures should use this, the other 20,000 texture fetch requests should continue to use the original. --- indra/newview/lltexturefetch.cpp | 17 +++++++++++++---- indra/newview/lltexturefetch.h | 3 ++- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index cc6dc64626..5e12c341d5 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. + * Copyright (C) 2012-2013, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -2376,6 +2376,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mQAMode(qa_mode), mHttpRequest(NULL), mHttpOptions(NULL), + mHttpOptionsWithHeaders(NULL), mHttpHeaders(NULL), mHttpMetricsHeaders(NULL), mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID), @@ -2406,11 +2407,13 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHttpRequest = new LLCore::HttpRequest; mHttpOptions = new LLCore::HttpOptions; + mHttpOptionsWithHeaders = new LLCore::HttpOptions; + mHttpOptionsWithHeaders->setWantHeaders(true); mHttpHeaders = new LLCore::HttpHeaders; // *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ? - mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); + mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C); mHttpMetricsHeaders = new LLCore::HttpHeaders; - mHttpMetricsHeaders->mHeaders.push_back(HTTP_OUT_HEADER_CONTENT_TYPE + ": " + HTTP_CONTENT_LLSD_XML); + mHttpMetricsHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML); mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault(); } @@ -2431,6 +2434,12 @@ LLTextureFetch::~LLTextureFetch() mHttpOptions = NULL; } + if (mHttpOptionsWithHeaders) + { + mHttpOptionsWithHeaders->release(); + mHttpOptionsWithHeaders = NULL; + } + if (mHttpHeaders) { mHttpHeaders->release(); @@ -4043,7 +4052,7 @@ void LLTextureFetchDebugger::init() { mHttpHeaders = new LLCore::HttpHeaders; // *TODO: Should this be 'image/j2c' instead of 'image/x-j2c' ? - mHttpHeaders->mHeaders.push_back(HTTP_OUT_HEADER_ACCEPT + ": " + HTTP_CONTENT_IMAGE_X_J2C); + mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_IMAGE_X_J2C); } } diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 902a3d7a25..3c79a5a24d 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2012, Linden Research, Inc. + * Copyright (C) 2012-2013, Linden Research, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -351,6 +351,7 @@ private: // LLCurl interfaces used in the past. LLCore::HttpRequest * mHttpRequest; // Ttf LLCore::HttpOptions * mHttpOptions; // Ttf + LLCore::HttpOptions * mHttpOptionsWithHeaders; // Ttf LLCore::HttpHeaders * mHttpHeaders; // Ttf LLCore::HttpHeaders * mHttpMetricsHeaders; // Ttf LLCore::HttpRequest::policy_t mHttpPolicyClass; // T* -- cgit v1.2.3 From 5976dc144e774ae363cbf774337ccf663015cc6d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 15 Apr 2013 15:12:22 -0400 Subject: SH-4061 WIP - simulated failures/image fetch retries --- indra/newview/lltexturefetch.cpp | 113 ++++++++++++++++++++++++++++++-------- indra/newview/llviewertexture.cpp | 2 +- indra/newview/llvoavatar.cpp | 2 +- 3 files changed, 92 insertions(+), 25 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 026f36e205..8e78638c0a 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -63,6 +63,8 @@ #include "bufferarray.h" #include "bufferstream.h" +#include "llhttpretrypolicy.h" + bool LLTextureFetchDebugger::sDebuggerEnabled = false ; LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128); LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128); @@ -244,6 +246,25 @@ static const S32 HTTP_REQUESTS_IN_QUEUE_LOW_WATER = 20; // Active level at whi ////////////////////////////////////////////////////////////////////////////// +static const char* e_state_name[] = +{ + "INVALID", + "INIT", + "LOAD_FROM_TEXTURE_CACHE", + "CACHE_POST", + "LOAD_FROM_NETWORK", + "LOAD_FROM_SIMULATOR", + "WAIT_HTTP_RESOURCE", + "WAIT_HTTP_RESOURCE2", + "SEND_HTTP_REQ", + "WAIT_HTTP_REQ", + "DECODE_IMAGE", + "DECODE_IMAGE_UPDATE", + "WRITE_TO_CACHE", + "WAIT_ON_WRITE", + "DONE" +}; + class LLTextureFetchWorker : public LLWorkerClass, public LLCore::HttpHandler { @@ -552,6 +573,8 @@ private: LLCore::HttpStatus mGetStatus; std::string mGetReason; bool mFakeFailure; + LLAdaptiveRetryPolicy mFetchRetryPolicy; + // Work Data LLMutex mWorkMutex; @@ -896,7 +919,8 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mCacheReadCount(0U), mCacheWriteCount(0U), mResourceWaitCount(0U), - mFakeFailure(fake_failure) + mFakeFailure(fake_failure), + mFetchRetryPolicy(15.0,15.0,1.0,10) { mCanUseNET = mUrl.empty() ; @@ -1277,6 +1301,20 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == LOAD_FROM_NETWORK) { + // Check for retries to previous server failures. + F32 wait_seconds; + if (mFetchRetryPolicy.shouldRetry(wait_seconds)) + { + if (wait_seconds <= 0.0) + { + llinfos << mID << " retrying now" << llendl; + } + else + { + //llinfos << mID << " waiting to retry for " << wait_seconds << " seconds" << llendl; + return false; + } + } static LLCachedControl use_http(gSavedSettings,"ImagePipelineUseHTTP"); // if (mHost != LLHost::invalid) get_url = false; @@ -1557,6 +1595,10 @@ bool LLTextureFetchWorker::doWork(S32 param) else if (http_service_unavail == mGetStatus) { LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL; + llinfos << "503: HTTP GET failed for: " << mUrl + << " Status: " << mGetStatus.toHex() + << " Reason: '" << mGetReason << "'" + << llendl; } else if (http_not_sat == mGetStatus) { @@ -1565,11 +1607,29 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { - llinfos << "HTTP GET failed for: " << mUrl + llinfos << "other: HTTP GET failed for: " << mUrl << " Status: " << mGetStatus.toHex() << " Reason: '" << mGetReason << "'" << llendl; } +#if 0 + if (isHttpServerErrorStatus(mGetStatus.mType)) + { + // Check for retry + F32 wait_seconds; + if (mFetchRetryPolicy.shouldRetry(wait_seconds)) + { + llinfos << mID << " status " << (S32) mGetStatus.mType << " will retry after " << wait_seconds << llendl; + setState(INIT); + releaseHttpSemaphore(); + return false; + } + else + { + llinfos << mID << " will not retry on status " << (S32) mGetStatus.mType << llendl; + } + } +#endif mUrl.clear(); if (cur_size > 0) @@ -1907,12 +1967,33 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe if (mFakeFailure) { - llwarns << "For debugging, setting fake failure status for texture " << mID << llendl; + llwarns << mID << " for debugging, setting fake failure status for texture " << mID << llendl; response->setStatus(LLCore::HttpStatus(500)); + setFakeFailure(false); } bool success = true; bool partial = false; LLCore::HttpStatus status(response->getStatus()); + if (!status && (mFTType == FTT_SERVER_BAKE)) + { + llinfos << mID << " state " << e_state_name[mState] << llendl; + mFetchRetryPolicy.onFailure(response); + F32 retry_after; + if (mFetchRetryPolicy.shouldRetry(retry_after)) + { + llinfos << mID << " should retry after " << retry_after << ", resetting state to INIT" << llendl; + mFetcher->removeFromHTTPQueue(mID, 0); + std::string reason(status.toString()); + setGetStatus(status, reason); + releaseHttpSemaphore(); + setState(INIT); + return; + } + else + { + llinfos << mID << " should not retry" << llendl; + } + } LL_DEBUGS("Texture") << "HTTP COMPLETE: " << mID << " status: " << status.toHex() @@ -1934,7 +2015,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe success = false; if (mFTType != FTT_MAP_TILE) // missing map tiles are normal, don't complain about them. { - llwarns << "CURL GET FAILED, status: " << status.toHex() + llwarns << mID << " CURL GET FAILED, status: " << status.toHex() << " reason: " << reason << llendl; } } @@ -2488,7 +2569,11 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const { return false; } - + + if (f_type == FTT_SERVER_BAKE) + { + llinfos << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << llendl; + } LLTextureFetchWorker* worker = getWorker(id) ; if (worker) { @@ -3248,24 +3333,6 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) void LLTextureFetchWorker::setState(e_state new_state) { - static const char* e_state_name[] = - { - "INVALID", - "INIT", - "LOAD_FROM_TEXTURE_CACHE", - "CACHE_POST", - "LOAD_FROM_NETWORK", - "LOAD_FROM_SIMULATOR", - "WAIT_HTTP_RESOURCE", - "WAIT_HTTP_RESOURCE2", - "SEND_HTTP_REQ", - "WAIT_HTTP_REQ", - "DECODE_IMAGE", - "DECODE_IMAGE_UPDATE", - "WRITE_TO_CACHE", - "WAIT_ON_WRITE", - "DONE" - }; LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; mState = new_state; } diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 5f4c66a04c..8f7c8e40b7 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -1826,7 +1826,7 @@ bool LLViewerFetchedTexture::updateFetch() // We finished but received no data if (current_discard < 0) { - const S32 MAX_FETCH_FAILURE = 3; + const S32 MAX_FETCH_FAILURE = 1; mFetchFailureCount++; if (getFTType() != FTT_MAP_TILE) { diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index cf4cc64ac3..a2ba8f36aa 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -7302,7 +7302,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 ); if (id == image_baked->getID()) { - LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL; + //LL_DEBUGS("Avatar") << avString() << " i " << i << " id " << id << LL_ENDL; mBakedTextureDatas[i].mIsLoaded = true; mBakedTextureDatas[i].mLastTextureID = id; mBakedTextureDatas[i].mIsUsed = true; -- cgit v1.2.3 From 7182203ebf4ba914c3a49f9593b1ed831fa6c1e9 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 15 Apr 2013 17:46:28 -0400 Subject: SH-4061 WIP - moved all retry logic into lltexturefetch, some cleanup. Debug setting now defines a fake failure rate. --- indra/newview/app_settings/logcontrol.xml | 0 indra/newview/app_settings/settings.xml | 6 ++--- indra/newview/lltexturefetch.cpp | 37 +++++++++++++------------ indra/newview/lltexturefetch.h | 2 +- indra/newview/llviewertexture.cpp | 45 +++++++------------------------ indra/newview/llviewertexture.h | 1 - 6 files changed, 33 insertions(+), 58 deletions(-) mode change 100644 => 100755 indra/newview/app_settings/logcontrol.xml (limited to 'indra/newview') diff --git a/indra/newview/app_settings/logcontrol.xml b/indra/newview/app_settings/logcontrol.xml old mode 100644 new mode 100755 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0b7f99ebc1..18a33b3542 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11130,16 +11130,16 @@ Value 0 - TextureFetchFakeFailures + TextureFetchFakeFailureRate Comment Simulate HTTP fetch failures for some server bake textures. Persist 1 Type - Boolean + F32 Value - 0 + 0.0 TextureFetchSource diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 8e78638c0a..2cebd4b6eb 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -410,13 +410,11 @@ public: // Inherited from LLCore::HttpHandler // Threads: Ttf virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response); - - void setFakeFailure(bool fake_failure) { mFakeFailure = fake_failure; } protected: LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, - F32 priority, S32 discard, S32 size, bool fake_failure); + F32 priority, S32 discard, S32 size); private: @@ -572,7 +570,6 @@ private: S32 mActiveCount; LLCore::HttpStatus mGetStatus; std::string mGetReason; - bool mFakeFailure; LLAdaptiveRetryPolicy mFetchRetryPolicy; @@ -864,8 +861,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, const LLHost& host, // Simulator host F32 priority, // Priority S32 discard, // Desired discard - S32 size, // Desired size - bool fake_failure) // For testing, simulate http failure if true. + S32 size) // Desired size : LLWorkerClass(fetcher, "TextureFetch"), LLCore::HttpHandler(), mState(INIT), @@ -919,7 +915,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mCacheReadCount(0U), mCacheWriteCount(0U), mResourceWaitCount(0U), - mFakeFailure(fake_failure), mFetchRetryPolicy(15.0,15.0,1.0,10) { mCanUseNET = mUrl.empty() ; @@ -1179,6 +1174,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; + // fall through } @@ -1315,6 +1311,7 @@ bool LLTextureFetchWorker::doWork(S32 param) return false; } } + static LLCachedControl use_http(gSavedSettings,"ImagePipelineUseHTTP"); // if (mHost != LLHost::invalid) get_url = false; @@ -1965,11 +1962,14 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); } - if (mFakeFailure) + static LLCachedControl fake_failure_rate(gSavedSettings, "TextureFetchFakeFailureRate"); + F32 rand_val = ll_frand(); + F32 rate = fake_failure_rate; + if (mFTType == FTT_SERVER_BAKE && (fake_failure_rate > 0.0) && (rand_val < fake_failure_rate)) { - llwarns << mID << " for debugging, setting fake failure status for texture " << mID << llendl; - response->setStatus(LLCore::HttpStatus(500)); - setFakeFailure(false); + llwarns << mID << " for debugging, setting fake failure status for texture " << mID + << " (rand was " << rand_val << "/" << rate << ")" << llendl; + response->setStatus(LLCore::HttpStatus(503)); } bool success = true; bool partial = false; @@ -1981,12 +1981,12 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe F32 retry_after; if (mFetchRetryPolicy.shouldRetry(retry_after)) { - llinfos << mID << " should retry after " << retry_after << ", resetting state to INIT" << llendl; + llinfos << mID << " should retry after " << retry_after << ", resetting state to LOAD_FROM_NETWORK" << llendl; mFetcher->removeFromHTTPQueue(mID, 0); std::string reason(status.toString()); setGetStatus(status, reason); releaseHttpSemaphore(); - setState(INIT); + setState(LOAD_FROM_NETWORK); return; } else @@ -2559,7 +2559,7 @@ LLTextureFetch::~LLTextureFetch() } bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, - S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http, bool fake_failure) + S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http) { if(mFetcherLocked) { @@ -2633,7 +2633,6 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const worker->setDesiredDiscard(desired_discard, desired_size); worker->setCanUseHTTP(can_use_http); worker->setUrl(url); - worker->setFakeFailure(fake_failure); if (!worker->haveWork()) { worker->setState(LLTextureFetchWorker::INIT); @@ -2648,7 +2647,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const } else { - worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size, fake_failure); + worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size); lockQueue(); // +Mfq mRequestMap[id] = worker; unlockQueue(); // -Mfq @@ -3333,7 +3332,11 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) void LLTextureFetchWorker::setState(e_state new_state) { - LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; + if (mFTType == FTT_SERVER_BAKE) + { +// LL_INFOS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; + } +// LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; mState = new_state; } diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 12226d51c8..5e2b55dbbb 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -78,7 +78,7 @@ public: // Threads: T* (but Tmain mostly) bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, - S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http, bool fake_failure); + S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http); // Requests that a fetch operation be deleted from the queue. // If @cancel is true, also stops any I/O operations pending. diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 8f7c8e40b7..45b402f0f6 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -962,8 +962,6 @@ void LLViewerFetchedTexture::init(bool firstinit) // does not contain this image. mIsMissingAsset = FALSE; - mFetchFailureCount = 0; - mLoadedCallbackDesiredDiscardLevel = S8_MAX; mPauseLoadedCallBacks = FALSE ; @@ -1826,35 +1824,17 @@ bool LLViewerFetchedTexture::updateFetch() // We finished but received no data if (current_discard < 0) { - const S32 MAX_FETCH_FAILURE = 1; - mFetchFailureCount++; if (getFTType() != FTT_MAP_TILE) { - llwarns << "Fetch failure for " << mID << " failure count " << mFetchFailureCount - << " status " << mLastHttpGetStatus.toHex() << llendl; - } - // Will retry server-bake textures under a limited set of circumstances. - if (getFTType() == FTT_SERVER_BAKE && - mLastHttpGetStatus.isHttpStatus() && - mLastHttpGetStatus.mType >= 500 && - mLastHttpGetStatus.mType <= 599 && // Only retry 5xx failures. - mFetchFailureCount < MAX_FETCH_FAILURE) - { - llwarns << "Will retry fetch" << llendl; - } - else // Otherwise, assume the image is missing. - { - if (getFTType() != FTT_MAP_TILE) - { - llwarns << "!mIsFetching, setting as missing, decode_priority " << decode_priority - << " mRawDiscardLevel " << mRawDiscardLevel - << " current_discard " << current_discard - << " stats " << mLastHttpGetStatus.toHex() - << llendl; - } - setIsMissingAsset(); - desired_discard = -1; + llwarns << mID + << " Fetch failure, setting as missing, decode_priority " << decode_priority + << " mRawDiscardLevel " << mRawDiscardLevel + << " current_discard " << current_discard + << " stats " << mLastHttpGetStatus.toHex() + << llendl; } + setIsMissingAsset(); + desired_discard = -1; } else { @@ -1968,14 +1948,8 @@ bool LLViewerFetchedTexture::updateFetch() // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; - bool fake_failure = false; - const bool debug_setting_fake_failures = gSavedSettings.getBOOL("TextureFetchFakeFailures"); - if (getFTType() == FTT_SERVER_BAKE && mFetchFailureCount == 0 && debug_setting_fake_failures) - { - fake_failure = true; - } fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority, - w, h, c, desired_discard, needsAux(), mCanUseHTTP, fake_failure); + w, h, c, desired_discard, needsAux(), mCanUseHTTP); if (fetch_request_created) { @@ -2072,7 +2046,6 @@ void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing) else { llinfos << mID << ": un-flagging missing asset" << llendl; - mFetchFailureCount = 0; } mIsMissingAsset = is_missing; } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 91e903ffd6..bf6aadd218 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -452,7 +452,6 @@ protected: FTType mFTType; // What category of image is this - map tile, server bake, etc? mutable BOOL mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. - S32 mFetchFailureCount; // How many times has a fetch failed in a way that suggests the asset is missing? typedef std::list callback_list_t; S8 mLoadedCallbackDesiredDiscardLevel; -- cgit v1.2.3 From 68cdbf387cf876da8833157b76048991120dc3f6 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 15 Apr 2013 18:03:31 -0400 Subject: SH-4061 WIP - comments, timing of retries --- indra/newview/lltexturefetch.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 2cebd4b6eb..7b719190a4 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -915,7 +915,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mCacheReadCount(0U), mCacheWriteCount(0U), mResourceWaitCount(0U), - mFetchRetryPolicy(15.0,15.0,1.0,10) + mFetchRetryPolicy(10.0,3600.0,2.0,10) { mCanUseNET = mUrl.empty() ; @@ -1981,7 +1981,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe F32 retry_after; if (mFetchRetryPolicy.shouldRetry(retry_after)) { - llinfos << mID << " should retry after " << retry_after << ", resetting state to LOAD_FROM_NETWORK" << llendl; + llinfos << mID << " will retry after " << retry_after << " seconds, resetting state to LOAD_FROM_NETWORK" << llendl; mFetcher->removeFromHTTPQueue(mID, 0); std::string reason(status.toString()); setGetStatus(status, reason); @@ -1991,7 +1991,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe } else { - llinfos << mID << " should not retry" << llendl; + llinfos << mID << " will not retry" << llendl; } } @@ -3334,9 +3334,12 @@ void LLTextureFetchWorker::setState(e_state new_state) { if (mFTType == FTT_SERVER_BAKE) { + // NOTE: turning on these log statements is a reliable way to get + // blurry images fairly frequently. Presumably this is an + // indication of some subtle timing or locking issue. + // LL_INFOS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; } -// LL_DEBUGS("Texture") << "id: " << mID << " FTType: " << mFTType << " disc: " << mDesiredDiscard << " sz: " << mDesiredSize << " state: " << e_state_name[mState] << " => " << e_state_name[new_state] << llendl; mState = new_state; } -- cgit v1.2.3 From 24b9657597be6d0b7af472d5deda4b4828ead606 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 15 Apr 2013 20:35:26 -0400 Subject: SH-4061 WIP - improved retry policy test, turned up and fixed a bug in getSecondsUntilRetryAfter --- indra/newview/tests/llhttpretrypolicy_test.cpp | 70 +++++++++++++------------- 1 file changed, 36 insertions(+), 34 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp index 42bb9abe90..6fa3a57364 100755 --- a/indra/newview/tests/llhttpretrypolicy_test.cpp +++ b/indra/newview/tests/llhttpretrypolicy_test.cpp @@ -216,21 +216,23 @@ void RetryPolicyTestObject::test<6>() time_t nowseconds; time(&nowseconds); - std::string str3 = LLDate((F64)nowseconds).asRFC1123(); + std::string str3 = LLDate((F64)(nowseconds+44)).asRFC1123(); seconds_to_wait = F32_MAX; success = getSecondsUntilRetryAfter(str3, seconds_to_wait); + std::cerr << " str3 [" << str3 << "]" << std::endl; ensure("parse 3", success); - ensure_approximately_equals("parse 3", seconds_to_wait, 0.0F, 6); + ensure_approximately_equals("parse 3", seconds_to_wait, 44.0F, 2); } // Test retry-after field in both llmessage and CoreHttp headers. template<> template<> void RetryPolicyTestObject::test<7>() { + std::cerr << "7 starts" << std::endl; + LLSD sd_headers; time_t nowseconds; time(&nowseconds); - sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = LLDate((F64)nowseconds).asRFC1123(); LLAdaptiveRetryPolicy policy(17.0,644.0,3.0,5); F32 seconds_to_wait; bool should_retry; @@ -245,40 +247,40 @@ void RetryPolicyTestObject::test<7>() ensure_approximately_equals("header 1", seconds_to_wait, 17.0F, 6); // retry header should override, give delay of 0 + std::string date_string = LLDate((F64)(nowseconds+7)).asRFC1123(); + sd_headers[HTTP_IN_HEADER_RETRY_AFTER] = date_string; policy.onFailure(503,sd_headers); should_retry = policy.shouldRetry(seconds_to_wait); ensure("header 2", should_retry); - ensure_approximately_equals("header 2", seconds_to_wait, 0.0F, 6); - - // retry header in LLCore::HttpHeaders - { - LLCore::HttpResponse *response = new LLCore::HttpResponse(); - LLCore::HttpHeaders *headers = new LLCore::HttpHeaders(); - response->setStatus(503); - response->setHeaders(headers); - headers->append(HTTP_IN_HEADER_RETRY_AFTER, std::string("600")); - policy.onFailure(response); - should_retry = policy.shouldRetry(seconds_to_wait); - ensure("header 3",should_retry); - ensure_approximately_equals("header 3", seconds_to_wait, 600.0F, 6); - response->release(); - } - - // retry header in LLCore::HttpHeaders - { - LLCore::HttpResponse *response = new LLCore::HttpResponse(); - LLCore::HttpHeaders *headers = new LLCore::HttpHeaders(); - response->setStatus(503); - response->setHeaders(headers); - LLSD sd_headers; - time(&nowseconds); - headers->append(HTTP_IN_HEADER_RETRY_AFTER,LLDate((F64)nowseconds).asRFC1123()); - policy.onFailure(response); - should_retry = policy.shouldRetry(seconds_to_wait); - ensure("header 4",should_retry); - ensure_approximately_equals("header 4", seconds_to_wait, 0.0F, 6); - response->release(); - } + ensure_approximately_equals("header 2", seconds_to_wait, 7.0F, 2); + + LLCore::HttpResponse *response; + LLCore::HttpHeaders *headers; + + response = new LLCore::HttpResponse(); + headers = new LLCore::HttpHeaders(); + response->setStatus(503); + response->setHeaders(headers); + headers->append(HTTP_IN_HEADER_RETRY_AFTER, std::string("600")); + policy.onFailure(response); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 3",should_retry); + ensure_approximately_equals("header 3", seconds_to_wait, 600.0F, 6); + response->release(); + + response = new LLCore::HttpResponse(); + headers = new LLCore::HttpHeaders(); + response->setStatus(503); + response->setHeaders(headers); + time(&nowseconds); + date_string = LLDate((F64)(nowseconds+77)).asRFC1123(); + std::cerr << "date_string [" << date_string << "]" << std::endl; + headers->append(HTTP_IN_HEADER_RETRY_AFTER,date_string); + policy.onFailure(response); + should_retry = policy.shouldRetry(seconds_to_wait); + ensure("header 4",should_retry); + ensure_approximately_equals("header 4", seconds_to_wait, 77.0F, 2); + response->release(); // Timeout should be clamped at max. policy.onFailure(500,LLSD()); -- cgit v1.2.3 From 9cbbb45a0ca8a56707125cdb3f6ea95de7f9deef Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 16 Apr 2013 09:19:35 -0400 Subject: SH-4061 WIP - cleanup --- indra/newview/lltexturefetch.cpp | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index ce7bd61ce4..1a6a308230 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1609,24 +1609,6 @@ bool LLTextureFetchWorker::doWork(S32 param) << " Reason: '" << mGetReason << "'" << llendl; } -#if 0 - if (isHttpServerErrorStatus(mGetStatus.mType)) - { - // Check for retry - F32 wait_seconds; - if (mFetchRetryPolicy.shouldRetry(wait_seconds)) - { - llinfos << mID << " status " << (S32) mGetStatus.mType << " will retry after " << wait_seconds << llendl; - setState(INIT); - releaseHttpSemaphore(); - return false; - } - else - { - llinfos << mID << " will not retry on status " << (S32) mGetStatus.mType << llendl; - } - } -#endif mUrl.clear(); if (cur_size > 0) -- cgit v1.2.3 From 0a413e1dc82bbe18c5c9fe510b10e33f8fb0a93c Mon Sep 17 00:00:00 2001 From: "prep@lindenlab.com" Date: Tue, 16 Apr 2013 11:54:16 -0500 Subject: Fix for SH-4108 - observer does not see the outfit change when closing appearance panel. --- indra/newview/llsidepanelappearance.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 7b89e0617b..3c21219dc1 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -136,6 +136,7 @@ void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj) } else { + LLVOAvatarSelf::onCustomizeEnd(FALSE); mLLFloaterSidePanelContainer->close(); } } -- cgit v1.2.3 From e3bad9fb86c3f44ad67488402ce2e46743a2422e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 16 Apr 2013 20:27:49 -0400 Subject: SH-4061 WIP - fix for build issues on mac, reset the retry policy on success. --- indra/newview/llhttpretrypolicy.cpp | 18 ++++++++++--- indra/newview/llhttpretrypolicy.h | 16 +++++++++--- indra/newview/lltexturefetch.cpp | 4 +++ indra/newview/tests/llhttpretrypolicy_test.cpp | 35 +++++++++++++++++++++----- 4 files changed, 59 insertions(+), 14 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llhttpretrypolicy.cpp b/indra/newview/llhttpretrypolicy.cpp index 10b923be5a..80d97e4362 100755 --- a/indra/newview/llhttpretrypolicy.cpp +++ b/indra/newview/llhttpretrypolicy.cpp @@ -32,11 +32,16 @@ LLAdaptiveRetryPolicy::LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 b mMinDelay(min_delay), mMaxDelay(max_delay), mBackoffFactor(backoff_factor), - mMaxRetries(max_retries), - mDelay(min_delay), - mRetryCount(0), - mShouldRetry(true) + mMaxRetries(max_retries) { + init(); +} + +void LLAdaptiveRetryPolicy::init() +{ + mDelay = mMinDelay; + mRetryCount = 0; + mShouldRetry = true; } bool LLAdaptiveRetryPolicy::getRetryAfter(const LLSD& headers, F32& retry_header_time) @@ -59,6 +64,11 @@ bool LLAdaptiveRetryPolicy::getRetryAfter(const LLCore::HttpHeaders *headers, F3 return false; } +void LLAdaptiveRetryPolicy::onSuccess() +{ + init(); +} + void LLAdaptiveRetryPolicy::onFailure(S32 status, const LLSD& headers) { F32 retry_header_time; diff --git a/indra/newview/llhttpretrypolicy.h b/indra/newview/llhttpretrypolicy.h index 6f63f047de..1fb0cac03f 100755 --- a/indra/newview/llhttpretrypolicy.h +++ b/indra/newview/llhttpretrypolicy.h @@ -42,7 +42,11 @@ class LLHTTPRetryPolicy: public LLThreadSafeRefCount { public: LLHTTPRetryPolicy() {} + virtual ~LLHTTPRetryPolicy() {} + // Call after a sucess to reset retry state. + + virtual void onSuccess() = 0; // Call once after an HTTP failure to update state. virtual void onFailure(S32 status, const LLSD& headers) = 0; @@ -58,6 +62,9 @@ class LLAdaptiveRetryPolicy: public LLHTTPRetryPolicy public: LLAdaptiveRetryPolicy(F32 min_delay, F32 max_delay, F32 backoff_factor, U32 max_retries); + // virtual + void onSuccess(); + // virtual void onFailure(S32 status, const LLSD& headers); // virtual @@ -66,16 +73,17 @@ public: bool shouldRetry(F32& seconds_to_wait) const; protected: + void init(); bool getRetryAfter(const LLSD& headers, F32& retry_header_time); bool getRetryAfter(const LLCore::HttpHeaders *headers, F32& retry_header_time); void onFailureCommon(S32 status, bool has_retry_header_time, F32 retry_header_time); private: - F32 mMinDelay; // delay never less than this value - F32 mMaxDelay; // delay never exceeds this value - F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay. - U32 mMaxRetries; // maximum number of times shouldRetry will return true. + const F32 mMinDelay; // delay never less than this value + const F32 mMaxDelay; // delay never exceeds this value + const F32 mBackoffFactor; // delay increases by this factor after each retry, up to mMaxDelay. + const U32 mMaxRetries; // maximum number of times shouldRetry will return true. F32 mDelay; // current default delay. U32 mRetryCount; // number of times shouldRetry has been called. LLTimer mRetryTimer; // time until next retry. diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 1a6a308230..774c925fa1 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1976,6 +1976,10 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe llinfos << mID << " will not retry" << llendl; } } + else + { + mFetchRetryPolicy.onSuccess(); + } LL_DEBUGS("Texture") << "HTTP COMPLETE: " << mID << " status: " << status.toHex() diff --git a/indra/newview/tests/llhttpretrypolicy_test.cpp b/indra/newview/tests/llhttpretrypolicy_test.cpp index 6fa3a57364..ed7f3ba326 100755 --- a/indra/newview/tests/llhttpretrypolicy_test.cpp +++ b/indra/newview/tests/llhttpretrypolicy_test.cpp @@ -45,7 +45,7 @@ void RetryPolicyTestObject::test<1>() LLSD headers; F32 wait_seconds; - // No retry until we've finished a try. + // No retry until we've failed a try. ensure("never retry 0", !never_retry.shouldRetry(wait_seconds)); // 0 retries max. @@ -74,7 +74,7 @@ void RetryPolicyTestObject::test<3>() bool should_retry; U32 frac_bits = 6; - // No retry until we've finished a try. + // No retry until we've failed a try. ensure("basic_retry 0", !basic_retry.shouldRetry(wait_seconds)); // Starting wait 1.0 @@ -105,6 +105,29 @@ void RetryPolicyTestObject::test<3>() basic_retry.onFailure(500,headers); should_retry = basic_retry.shouldRetry(wait_seconds); ensure("basic_retry 5", !should_retry); + + // Max retries, should fail now. + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 5", !should_retry); + + // After a success, should reset to the starting state. + basic_retry.onSuccess(); + + // No retry until we've failed a try. + ensure("basic_retry 6", !basic_retry.shouldRetry(wait_seconds)); + + // Starting wait 1.0 + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 7", should_retry); + ensure_approximately_equals("basic_retry 7", wait_seconds, 1.0F, frac_bits); + + // Double wait to 2.0 + basic_retry.onFailure(500,headers); + should_retry = basic_retry.shouldRetry(wait_seconds); + ensure("basic_retry 8", should_retry); + ensure_approximately_equals("basic_retry 8", wait_seconds, 2.0F, frac_bits); } // Retries should stop as soon as a non-5xx error is received. @@ -221,7 +244,7 @@ void RetryPolicyTestObject::test<6>() success = getSecondsUntilRetryAfter(str3, seconds_to_wait); std::cerr << " str3 [" << str3 << "]" << std::endl; ensure("parse 3", success); - ensure_approximately_equals("parse 3", seconds_to_wait, 44.0F, 2); + ensure_approximately_equals_range("parse 3", seconds_to_wait, 44.0F, 2.0F); } // Test retry-after field in both llmessage and CoreHttp headers. @@ -237,7 +260,7 @@ void RetryPolicyTestObject::test<7>() F32 seconds_to_wait; bool should_retry; - // No retry until we've finished a try. + // No retry until we've failed a try. ensure("header 0", !policy.shouldRetry(seconds_to_wait)); // no retry header, use default. @@ -252,7 +275,7 @@ void RetryPolicyTestObject::test<7>() policy.onFailure(503,sd_headers); should_retry = policy.shouldRetry(seconds_to_wait); ensure("header 2", should_retry); - ensure_approximately_equals("header 2", seconds_to_wait, 7.0F, 2); + ensure_approximately_equals_range("header 2", seconds_to_wait, 7.0F, 2.0F); LLCore::HttpResponse *response; LLCore::HttpHeaders *headers; @@ -279,7 +302,7 @@ void RetryPolicyTestObject::test<7>() policy.onFailure(response); should_retry = policy.shouldRetry(seconds_to_wait); ensure("header 4",should_retry); - ensure_approximately_equals("header 4", seconds_to_wait, 77.0F, 2); + ensure_approximately_equals_range("header 4", seconds_to_wait, 77.0F, 2.0F); response->release(); // Timeout should be clamped at max. -- cgit v1.2.3 From 8cf67fe50cfa070e5aa786acdb9bce58c350d840 Mon Sep 17 00:00:00 2001 From: prep Date: Wed, 17 Apr 2013 10:33:33 -0400 Subject: Fix for SH-4104: Inventory window does not close --- indra/newview/llfloatersidepanelcontainer.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index b1f9a18d6f..4dd558c9c0 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -69,6 +69,10 @@ void LLFloaterSidePanelContainer::onClickCloseBtn() LLSidepanelAppearance* panel_appearance = dynamic_cast(getPanel("appearance")); panel_appearance->onClose(this); } + else + { + LLFloater::onClickCloseBtn(); + } } else { -- cgit v1.2.3 From 392f561b6c28aede2b61bc9cc2cc75de587926b6 Mon Sep 17 00:00:00 2001 From: prep Date: Wed, 17 Apr 2013 11:08:40 -0400 Subject: Fix for SH-4123: outfit update corrected for edit/save/abandon sequence --- indra/newview/llsidepanelappearance.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 3c21219dc1..75da23b558 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -90,8 +90,9 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) { + //revert curernt edits mEditWearable->revertChanges(); - LLAppearanceMgr::getInstance()->wearBaseOutfit(); + LLVOAvatarSelf::onCustomizeEnd(FALSE); mLLFloaterSidePanelContainer->close(); return true; } -- cgit v1.2.3 From b224b8978adfd42c89e1c66bc5495ead8fa1e85d Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 17 Apr 2013 11:32:23 -0400 Subject: SH-4061 WIP - request headers for server-bake images --- indra/newview/lltexturefetch.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 774c925fa1..346374ef4e 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1524,12 +1524,14 @@ bool LLTextureFetchWorker::doWork(S32 param) << LL_ENDL; // Will call callbackHttpGet when curl request completes + // Only server bake images use the returned headers currently, for getting retry-after field. + HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions; mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass, mWorkPriority, mUrl, mRequestedOffset, mRequestedSize, - mFetcher->mHttpOptions, + options, mFetcher->mHttpHeaders, this); } -- cgit v1.2.3 From b29e6f656eb28d557ef4488a022b6757a58d29e1 Mon Sep 17 00:00:00 2001 From: prep Date: Wed, 17 Apr 2013 11:32:49 -0400 Subject: Fix for SH-4124: Closing appearance panel also closes the edit wearable panel if it was active --- indra/newview/llsidepanelappearance.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 75da23b558..77e9604460 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -92,6 +92,7 @@ bool LLSidepanelAppearance::callBackExitWithoutSaveViaClose(const LLSD& notifica { //revert curernt edits mEditWearable->revertChanges(); + toggleWearableEditPanel(FALSE); LLVOAvatarSelf::onCustomizeEnd(FALSE); mLLFloaterSidePanelContainer->close(); return true; @@ -138,6 +139,7 @@ void LLSidepanelAppearance::onClose(LLFloaterSidePanelContainer* obj) else { LLVOAvatarSelf::onCustomizeEnd(FALSE); + toggleWearableEditPanel(FALSE); mLLFloaterSidePanelContainer->close(); } } -- cgit v1.2.3 From 17af76fae18e305d0a42192a326648f00c84d1f3 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 18 Apr 2013 13:56:16 -0400 Subject: SH-4128 WIP - use the AISv3 inventory cap when available for cof link deletion, hook in to callback mechanism so all link operations should be done before outfit is worn. --- indra/newview/llappearancemgr.cpp | 20 ++----- indra/newview/llappearancemgr.h | 2 +- indra/newview/lltexturefetch.cpp | 4 +- indra/newview/llviewerinventory.cpp | 101 ++++++++++++++++++++++++++++++++++++ indra/newview/llviewerinventory.h | 4 ++ indra/newview/llviewerregion.cpp | 1 + 6 files changed, 113 insertions(+), 19 deletions(-) mode change 100644 => 100755 indra/newview/llviewerinventory.cpp mode change 100644 => 100755 indra/newview/llviewerinventory.h (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 85f6f92278..f1a2141b99 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1661,7 +1661,7 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) } } -void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t* keep_items) +void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer cb) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -1674,19 +1674,8 @@ void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_lin continue; if (item->getIsLinkType()) { -#if 0 - if (keep_items && keep_items->find(item) != LLInventoryModel::item_array_t::FAIL) - { - llinfos << "preserved item" << llendl; - } - else - { - gInventory.purgeObject(item->getUUID()); - } -#else - gInventory.purgeObject(item->getUUID()); + remove_inventory_item(item->getUUID(), cb); } -#endif } } @@ -1819,7 +1808,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // carried over (e.g. keeping old shape if the new outfit does not // contain one) bool keep_outfit_links = append; - purgeCategory(cof, keep_outfit_links, &all_items); + purgeCategory(cof, keep_outfit_links, link_waiter); gInventory.notifyObservers(); LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL; @@ -2824,7 +2813,7 @@ bool LLAppearanceMgr::updateBaseOutfit() updateClothingOrderingInfo(); // in a Base Outfit we do not remove items, only links - purgeCategory(base_outfit_id, false); + purgeCategory(base_outfit_id, false, NULL); LLPointer dirty_state_updater = new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state); @@ -3211,7 +3200,6 @@ void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr respond } LL_DEBUGS("Avatar") << "request url " << url << " my_cof_version " << cof_version << llendl; - //LLCurl::ResponderPtr responder_ptr; if (!responder_ptr.get()) { responder_ptr = new RequestAgentUpdateAppearanceResponder; diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 46252afbde..b933b4fc50 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -222,7 +222,7 @@ private: LLInventoryModel::item_array_t& gest_items, bool follow_folder_links); - void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLInventoryModel::item_array_t* keep_items = NULL); + void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer cb); static void onOutfitRename(const LLSD& notification, const LLSD& response); void setOutfitLocked(bool locked); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 346374ef4e..f7fbb19bdc 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1525,7 +1525,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // Will call callbackHttpGet when curl request completes // Only server bake images use the returned headers currently, for getting retry-after field. - HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions; + LLCore::HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions; mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass, mWorkPriority, mUrl, @@ -2569,7 +2569,7 @@ bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const if (f_type == FTT_SERVER_BAKE) { - llinfos << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << llendl; + LL_DEBUGS("Avatar") << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << llendl; } LLTextureFetchWorker* worker = getWorker(id) ; if (worker) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp old mode 100644 new mode 100755 index fff9821e86..316fca7769 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1179,6 +1179,107 @@ void move_inventory_item( gAgent.sendReliableMessage(); } +void handle_item_deletion(const LLUUID& item_id) +{ + LLPointer obj = gInventory.getItem(item_id); + if(obj) + { + // From item removeFromServer() + LLInventoryModel::LLCategoryUpdate up(obj->getParentUUID(), -1); + gInventory.accountForUpdate(up); + + // From purgeObject() + LLPreview::hide(item_id); + gInventory.deleteObject(item_id); + } +} + +class RemoveItemResponder: public LLHTTPClient::Responder +{ +public: + RemoveItemResponder(const LLUUID& item_id, LLPointer callback): + mItemUUID(item_id), + mCallback(callback) + { + } + /* virtual */ void httpSuccess() + { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + llinfos << "succeeded: " << ll_pretty_print_sd(content) << llendl; + + handle_item_deletion(mItemUUID); + + if (mCallback) + { + mCallback->fire(mItemUUID); + } + } + /*virtual*/ void httpFailure() + { + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + llwarns << "failed for " << mItemUUID << " content: " << ll_pretty_print_sd(content) << llendl; + } +private: + LLPointer mCallback; + const LLUUID mItemUUID; +}; + +void remove_inventory_item( + const LLUUID& item_id, + LLPointer cb) +{ + llinfos << "item_id: [" << item_id << "] " << llendl; + LLPointer obj = gInventory.getItem(item_id); + if(obj) + { + std::string cap; + if (gAgent.getRegion()) + { + cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); + } + if (!cap.empty()) + { + std::string url = cap + std::string("/item/") + item_id.asString(); + llinfos << "url: " << url << llendl; + LLCurl::ResponderPtr responder_ptr = new RemoveItemResponder(item_id,cb); + LLHTTPClient::del(url,responder_ptr); + } + else // no cap + { + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_RemoveInventoryItem); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_InventoryData); + msg->addUUIDFast(_PREHASH_ItemID, item_id); + gAgent.sendReliableMessage(); + + // Update inventory and call callback immediately since + // message-based system has no callback mechanism (!) + handle_item_deletion(item_id); + if (cb) + { + cb->fire(item_id); + } + } + } + else + { + llwarns << "remove_inventory_item called for nonexistent item " << item_id << llendl; + } +} + const LLUUID get_folder_by_itemtype(const LLInventoryItem *src) { LLUUID retval = LLUUID::null; diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h old mode 100644 new mode 100755 index 61b1b8d846..7cb62efb47 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -365,6 +365,10 @@ void move_inventory_item( const std::string& new_name, LLPointer cb); +void remove_inventory_item( + const LLUUID& item_id, + LLPointer cb); + const LLUUID get_folder_by_itemtype(const LLInventoryItem *src); void copy_inventory_from_notecard(const LLUUID& destination_id, diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index f0d81c599c..e77b29aca4 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1641,6 +1641,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("FetchInventory2"); capabilityNames.append("FetchInventoryDescendents2"); capabilityNames.append("IncrementCOFVersion"); + capabilityNames.append("InventoryAPIv3"); } capabilityNames.append("GetDisplayNames"); -- cgit v1.2.3 From e3ceb10c48b7ce339fab8c3c7a726bd4bf2e30e8 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 18 Apr 2013 17:31:35 -0400 Subject: SH-4128 WIP - avoid needless called to updateLinkedObjectsFromPurge() --- indra/newview/llinventorymodel.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) mode change 100644 => 100755 indra/newview/llinventorymodel.cpp (limited to 'indra/newview') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp old mode 100644 new mode 100755 index 8d7478233a..3d2fcdc494 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1171,8 +1171,14 @@ void LLInventoryModel::deleteObject(const LLUUID& id) mParentChildCategoryTree.erase(id); } addChangedMask(LLInventoryObserver::REMOVE, id); + bool is_link_type = obj->getIsLinkType(); obj = NULL; // delete obj - updateLinkedObjectsFromPurge(id); + // Can't have links to links, so there's no need for this update + // if the item removed is a link. + if (!is_link_type) + { + updateLinkedObjectsFromPurge(id); + } gInventory.notifyObservers(); } -- cgit v1.2.3 From 7b52a41e34e1fefd751d69be708b23df59774c6a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 18 Apr 2013 17:49:10 -0400 Subject: SH-4116 WIP - removed follow_folder_links behavior, which was used nowhere and isn't really desirable currently --- indra/newview/llappearancemgr.cpp | 49 ++++++++++++++++---------------------- indra/newview/llappearancemgr.h | 6 ++--- indra/newview/llinventorymodel.cpp | 33 +------------------------ indra/newview/llinventorymodel.h | 3 +-- 4 files changed, 24 insertions(+), 67 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index f1a2141b99..fffec223d7 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1204,8 +1204,7 @@ const LLViewerInventoryItem* LLAppearanceMgr::getBaseOutfitLink() cat_array, item_array, false, - is_category, - false); + is_category); for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); iter != item_array.end(); iter++) @@ -1738,7 +1737,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) if (!append) { LLInventoryModel::item_array_t gest_items; - getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false); + getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE); for(S32 i = 0; i < gest_items.count(); ++i) { LLViewerInventoryItem *gest_item = gest_items.get(i); @@ -1755,8 +1754,8 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // required parts are missing. // Preserve body parts from COF if appending. LLInventoryModel::item_array_t body_items; - getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART, false); - getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART, false); + getDescendentsOfAssetType(cof, body_items, LLAssetType::AT_BODYPART); + getDescendentsOfAssetType(category, body_items, LLAssetType::AT_BODYPART); if (append) reverse(body_items.begin(), body_items.end()); // Reduce body items to max of one per type. @@ -1766,8 +1765,8 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // - Wearables: include COF contents only if appending. LLInventoryModel::item_array_t wear_items; if (append) - getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING, false); - getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING, false); + getDescendentsOfAssetType(cof, wear_items, LLAssetType::AT_CLOTHING); + getDescendentsOfAssetType(category, wear_items, LLAssetType::AT_CLOTHING); // Reduce wearables to max of one per type. removeDuplicateItems(wear_items); filterWearableItems(wear_items, LLAgentWearables::MAX_CLOTHING_PER_TYPE); @@ -1775,15 +1774,15 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // - Attachments: include COF contents only if appending. LLInventoryModel::item_array_t obj_items; if (append) - getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT, false); - getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT, false); + getDescendentsOfAssetType(cof, obj_items, LLAssetType::AT_OBJECT); + getDescendentsOfAssetType(category, obj_items, LLAssetType::AT_OBJECT); removeDuplicateItems(obj_items); // - Gestures: include COF contents only if appending. LLInventoryModel::item_array_t gest_items; if (append) - getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE, false); - getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE, false); + getDescendentsOfAssetType(cof, gest_items, LLAssetType::AT_GESTURE); + getDescendentsOfAssetType(category, gest_items, LLAssetType::AT_GESTURE); removeDuplicateItems(gest_items); // Create links to new COF contents. @@ -1927,7 +1926,7 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id, S32 to_kill_count = 0; LLInventoryModel::item_array_t items; - getDescendentsOfAssetType(cat_id, items, type, false); + getDescendentsOfAssetType(cat_id, items, type); LLInventoryModel::item_array_t curr_items = items; removeDuplicateItems(items); if (max_items > 0) @@ -2009,7 +2008,6 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) //dumpCat(getCOF(),"COF, start"); - bool follow_folder_links = false; LLUUID current_outfit_id = getCOF(); // Find all the wearables that are in the COF's subtree. @@ -2017,7 +2015,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) LLInventoryModel::item_array_t wear_items; LLInventoryModel::item_array_t obj_items; LLInventoryModel::item_array_t gest_items; - getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items, follow_folder_links); + getUserDescendents(current_outfit_id, wear_items, obj_items, gest_items); // Get rid of non-links in case somehow the COF was corrupted. remove_non_link_items(wear_items); remove_non_link_items(obj_items); @@ -2113,8 +2111,7 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category, LLInventoryModel::item_array_t& items, - LLAssetType::EType type, - bool follow_folder_links) + LLAssetType::EType type) { LLInventoryModel::cat_array_t cats; LLIsType is_of_type(type); @@ -2122,15 +2119,13 @@ void LLAppearanceMgr::getDescendentsOfAssetType(const LLUUID& category, cats, items, LLInventoryModel::EXCLUDE_TRASH, - is_of_type, - follow_folder_links); + is_of_type); } void LLAppearanceMgr::getUserDescendents(const LLUUID& category, LLInventoryModel::item_array_t& wear_items, LLInventoryModel::item_array_t& obj_items, - LLInventoryModel::item_array_t& gest_items, - bool follow_folder_links) + LLInventoryModel::item_array_t& gest_items) { LLInventoryModel::cat_array_t wear_cats; LLFindWearables is_wearable; @@ -2138,8 +2133,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category, wear_cats, wear_items, LLInventoryModel::EXCLUDE_TRASH, - is_wearable, - follow_folder_links); + is_wearable); LLInventoryModel::cat_array_t obj_cats; LLIsType is_object( LLAssetType::AT_OBJECT ); @@ -2147,8 +2141,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category, obj_cats, obj_items, LLInventoryModel::EXCLUDE_TRASH, - is_object, - follow_folder_links); + is_object); // Find all gestures in this folder LLInventoryModel::cat_array_t gest_cats; @@ -2157,8 +2150,7 @@ void LLAppearanceMgr::getUserDescendents(const LLUUID& category, gest_cats, gest_items, LLInventoryModel::EXCLUDE_TRASH, - is_gesture, - follow_folder_links); + is_gesture); } void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append) @@ -2514,8 +2506,7 @@ void LLAppearanceMgr::removeAllClothesFromAvatar() dummy, clothing_items, LLInventoryModel::EXCLUDE_TRASH, - is_clothing, - false); + is_clothing); uuid_vec_t item_ids; for (LLInventoryModel::item_array_t::iterator it = clothing_items.begin(); it != clothing_items.end(); ++it) @@ -2910,7 +2901,7 @@ void LLAppearanceMgr::updateClothingOrderingInfo(LLUUID cat_id, bool update_base // COF is processed if cat_id is not specified LLInventoryModel::item_array_t wear_items; - getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING, false); + getDescendentsOfAssetType(cat_id, wear_items, LLAssetType::AT_CLOTHING); wearables_by_type_t items_by_type(LLWearableType::WT_COUNT); divvyWearablesByType(wear_items, items_by_type); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index b933b4fc50..6c014b1a4b 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -213,14 +213,12 @@ private: void getDescendentsOfAssetType(const LLUUID& category, LLInventoryModel::item_array_t& items, - LLAssetType::EType type, - bool follow_folder_links); + LLAssetType::EType type); void getUserDescendents(const LLUUID& category, LLInventoryModel::item_array_t& wear_items, LLInventoryModel::item_array_t& obj_items, - LLInventoryModel::item_array_t& gest_items, - bool follow_folder_links); + LLInventoryModel::item_array_t& gest_items); void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer cb); static void onOutfitRename(const LLSD& notification, const LLSD& response); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 3d2fcdc494..bbf284147a 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -624,8 +624,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, cat_array_t& cats, item_array_t& items, BOOL include_trash, - LLInventoryCollectFunctor& add, - BOOL follow_folder_links) + LLInventoryCollectFunctor& add) { // Start with categories if(!include_trash) @@ -652,36 +651,6 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, LLViewerInventoryItem* item = NULL; item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id); - // Follow folder links recursively. Currently never goes more - // than one level deep (for current outfit support) - // Note: if making it fully recursive, need more checking against infinite loops. - if (follow_folder_links && item_array) - { - S32 count = item_array->count(); - for(S32 i = 0; i < count; ++i) - { - item = item_array->get(i); - if (item && item->getActualType() == LLAssetType::AT_LINK_FOLDER) - { - LLViewerInventoryCategory *linked_cat = item->getLinkedCategory(); - if (linked_cat && linked_cat->getPreferredType() != LLFolderType::FT_OUTFIT) - // BAP - was - // LLAssetType::lookupIsEnsembleCategoryType(linked_cat->getPreferredType())) - // Change back once ensemble typing is in place. - { - if(add(linked_cat,NULL)) - { - // BAP should this be added here? May not - // matter if it's only being used in current - // outfit traversal. - cats.put(LLPointer(linked_cat)); - } - collectDescendentsIf(linked_cat->getUUID(), cats, items, include_trash, add, FALSE); - } - } - } - } - // Move onto items if(item_array) { diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 3aa29bd91d..0b017b7514 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -213,8 +213,7 @@ public: cat_array_t& categories, item_array_t& items, BOOL include_trash, - LLInventoryCollectFunctor& add, - BOOL follow_folder_links = FALSE); + LLInventoryCollectFunctor& add); // Collect all items in inventory that are linked to item_id. // Assumes item_id is itself not a linked item. -- cgit v1.2.3 From d807a9162662aa3b921020af2df2c30cc71b1b32 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Mon, 22 Apr 2013 16:48:02 -0400 Subject: SH-4128 WIP - more stages of outfit change now go through the callback mechanism for link removals --- indra/newview/llappearancemgr.cpp | 89 +++++++++++++++++++++++---------------- indra/newview/llappearancemgr.h | 17 ++++++-- 2 files changed, 66 insertions(+), 40 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index fffec223d7..21af5adf09 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -501,9 +501,11 @@ public: } }; -LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering): +LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering, + bool enforce_item_restrictions): mFireCount(0), - mUpdateBaseOrder(update_base_outfit_ordering) + mUpdateBaseOrder(update_base_outfit_ordering), + mEnforceItemRestrictions(enforce_item_restrictions) { selfStartPhase("update_appearance_on_destroy"); } @@ -517,7 +519,7 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() selfStopPhase("update_appearance_on_destroy"); - LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder); + LLAppearanceMgr::instance().updateAppearanceFromCOF(mUpdateBaseOrder, mEnforceItemRestrictions); } } @@ -1660,7 +1662,8 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) } } -void LLAppearanceMgr::purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer cb) +void LLAppearanceMgr::removeCategoryContents(const LLUUID& category, bool keep_outfit_links, + LLPointer cb) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -1726,6 +1729,18 @@ void LLAppearanceMgr::linkAll(const LLUUID& cat_uuid, } } +void LLAppearanceMgr::removeAll(LLInventoryModel::item_array_t& items_to_kill, + LLPointer cb) +{ + for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin(); + it != items_to_kill.end(); + ++it) + { + LLViewerInventoryItem *item = *it; + remove_inventory_item(item->getUUID(), cb); + } +} + void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) { LLViewerInventoryCategory *pcat = gInventory.getCategory(category); @@ -1807,8 +1822,7 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append) // carried over (e.g. keeping old shape if the new outfit does not // contain one) bool keep_outfit_links = append; - purgeCategory(cof, keep_outfit_links, link_waiter); - gInventory.notifyObservers(); + removeCategoryContents(cof, keep_outfit_links, link_waiter); LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL; } @@ -1945,34 +1959,20 @@ S32 LLAppearanceMgr::findExcessOrDuplicateItems(const LLUUID& cat_id, return to_kill_count; } - -void LLAppearanceMgr::enforceItemRestrictions() -{ - S32 purge_count = 0; - LLInventoryModel::item_array_t items_to_kill; - - purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_BODYPART, - 1, items_to_kill); - purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_CLOTHING, - LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill); - purge_count += findExcessOrDuplicateItems(getCOF(),LLAssetType::AT_OBJECT, - -1, items_to_kill); - if (items_to_kill.size()>0) - { - for (LLInventoryModel::item_array_t::iterator it = items_to_kill.begin(); - it != items_to_kill.end(); - ++it) - { - LLViewerInventoryItem *item = *it; - LL_DEBUGS("Avatar") << self_av_string() << "purging duplicate or excess item " << item->getName() << LL_ENDL; - gInventory.purgeObject(item->getUUID()); - } - gInventory.notifyObservers(); - } +void LLAppearanceMgr::findAllExcessOrDuplicateItems(const LLUUID& cat_id, + LLInventoryModel::item_array_t& items_to_kill) +{ + findExcessOrDuplicateItems(cat_id,LLAssetType::AT_BODYPART, + 1, items_to_kill); + findExcessOrDuplicateItems(cat_id,LLAssetType::AT_CLOTHING, + LLAgentWearables::MAX_CLOTHING_PER_TYPE, items_to_kill); + findExcessOrDuplicateItems(cat_id,LLAssetType::AT_OBJECT, + -1, items_to_kill); } -void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) +void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering, + bool enforce_item_restrictions) { if (mIsInUpdateAppearanceFromCOF) { @@ -1985,14 +1985,31 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool update_base_outfit_ordering) LL_DEBUGS("Avatar") << self_av_string() << "starting" << LL_ENDL; + if (enforce_item_restrictions) + { + LLInventoryModel::item_array_t items_to_kill; + findAllExcessOrDuplicateItems(getCOF(), items_to_kill); + if (items_to_kill.size()>0) + { + // The point here is just to call + // updateAppearanceFromCOF() again after excess items + // have been removed. That time we will set + // enforce_item_restrictions to false so we don't get + // caught in a perpetual loop. + LLPointer cb( + new LLUpdateAppearanceOnDestroy(update_base_outfit_ordering, false)); + + // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but + // this should catch anything that gets through. + removeAll(items_to_kill, cb); + return; + } + } + //checking integrity of the COF in terms of ordering of wearables, //checking and updating links' descriptions of wearables in the COF (before analyzed for "dirty" state) updateClothingOrderingInfo(LLUUID::null, update_base_outfit_ordering); - // Remove duplicate or excess wearables. Should normally be enforced at the UI level, but - // this should catch anything that gets through. - enforceItemRestrictions(); - // update dirty flag to see if the state of the COF matches // the saved outfit stored as a folder link updateIsDirty(); @@ -2804,7 +2821,7 @@ bool LLAppearanceMgr::updateBaseOutfit() updateClothingOrderingInfo(); // in a Base Outfit we do not remove items, only links - purgeCategory(base_outfit_id, false, NULL); + removeCategoryContents(base_outfit_id, false, NULL); LLPointer dirty_state_updater = new LLBoostFuncInventoryCallback(no_op_inventory_func, appearance_mgr_update_dirty_state); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 6c014b1a4b..0cc06ab210 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -49,7 +49,8 @@ class LLAppearanceMgr: public LLSingleton public: typedef std::vector wearables_by_type_t; - void updateAppearanceFromCOF(bool update_base_outfit_ordering = false); + void updateAppearanceFromCOF(bool update_base_outfit_ordering = false, + bool enforce_item_restrictions = true); bool needToSaveCOF(); void updateCOF(const LLUUID& category, bool append = false); void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append); @@ -65,7 +66,8 @@ public: LLAssetType::EType type, S32 max_items, LLInventoryModel::item_array_t& items_to_kill); - void enforceItemRestrictions(); + void findAllExcessOrDuplicateItems(const LLUUID& cat_id, + LLInventoryModel::item_array_t& items_to_kill); // Copy all items and the src category itself. void shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id, @@ -129,6 +131,10 @@ public: LLInventoryModel::item_array_t& items, LLPointer cb); + // And bulk removal. + void removeAll(LLInventoryModel::item_array_t& items, + LLPointer cb); + // Add COF link to individual item. void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer cb = NULL, const std::string description = ""); void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer cb = NULL, const std::string description = ""); @@ -220,7 +226,8 @@ private: LLInventoryModel::item_array_t& obj_items, LLInventoryModel::item_array_t& gest_items); - void purgeCategory(const LLUUID& category, bool keep_outfit_links, LLPointer cb); + void removeCategoryContents(const LLUUID& category, bool keep_outfit_links, + LLPointer cb); static void onOutfitRename(const LLSD& notification, const LLSD& response); void setOutfitLocked(bool locked); @@ -254,13 +261,15 @@ public: class LLUpdateAppearanceOnDestroy: public LLInventoryCallback { public: - LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false); + LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering = false, + bool enforce_item_restrictions = true); virtual ~LLUpdateAppearanceOnDestroy(); /* virtual */ void fire(const LLUUID& inv_item); private: U32 mFireCount; bool mUpdateBaseOrder; + bool mEnforceItemRestrictions; }; -- cgit v1.2.3 From 1bf66885617564c8df9baac3b45ed5e9d96ef153 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 23 Apr 2013 15:52:12 -0400 Subject: SH-4128 WIP - rewiring various link-deleting operations to support callbacks --- indra/newview/llagentwearables.cpp | 9 +- indra/newview/llappearancemgr.cpp | 203 ++++++++++++------------------------ indra/newview/llappearancemgr.h | 27 +++-- indra/newview/llfloatergesture.cpp | 2 +- indra/newview/llpaneloutfitedit.cpp | 4 +- indra/newview/llviewerinventory.h | 2 +- 6 files changed, 95 insertions(+), 152 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index c88694ef76..b4c3e33e0e 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -69,7 +69,7 @@ void wear_and_edit_cb(const LLUUID& inv_item) gAgentWearables.requestEditingWearable(inv_item); // Wear it. - LLAppearanceMgr::instance().wearItemOnAvatar(inv_item); + LLAppearanceMgr::instance().wearItemOnAvatar(inv_item,true); } /////////////////////////////////////////////////////////////////////////////// @@ -239,7 +239,7 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i } if (mTodo & CALL_RECOVERDONE) { - LLAppearanceMgr::instance().addCOFItemLink(inv_item,false); + LLAppearanceMgr::instance().addCOFItemLink(inv_item); gAgentWearables.recoverMissingWearableDone(); } /* @@ -247,7 +247,7 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i */ if (mTodo & CALL_CREATESTANDARDDONE) { - LLAppearanceMgr::instance().addCOFItemLink(inv_item,false); + LLAppearanceMgr::instance().addCOFItemLink(inv_item); gAgentWearables.createStandardWearablesDone(mType, mIndex); } if (mTodo & CALL_MAKENEWOUTFITDONE) @@ -256,7 +256,8 @@ void LLAgentWearables::addWearableToAgentInventoryCallback::fire(const LLUUID& i } if (mTodo & CALL_WEARITEM) { - LLAppearanceMgr::instance().addCOFItemLink(inv_item, true, NULL, mDescription); + LLAppearanceMgr::instance().addCOFItemLink(inv_item, + new LLUpdateAppearanceAndEditWearableOnDestroy(inv_item), mDescription); } } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 21af5adf09..634f5d1389 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -421,86 +421,6 @@ public: } }; -class LLCallAfterInventoryLinkMgr: public LLCallAfterInventoryBatchMgr -{ -public: - LLCallAfterInventoryLinkMgr(LLInventoryModel::item_array_t& src_items, - const LLUUID& dst_cat_id, - const std::string& phase_name, - nullary_func_t on_completion_func, - nullary_func_t on_failure_func = no_op, - F32 retry_after = DEFAULT_RETRY_AFTER_INTERVAL, - S32 max_retries = DEFAULT_MAX_RETRIES - ): - LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func, retry_after, max_retries) - { - addItems(src_items); - } - - virtual bool requestOperation(const LLUUID& item_id) - { - bool request_sent = false; - LLViewerInventoryItem *item = gInventory.getItem(item_id); - if (item) - { - if (item->getParentUUID() == mDstCatID) - { - LL_DEBUGS("Avatar") << "item " << item_id << " name " << item->getName() << " is already a child of " << mDstCatID << llendl; - return false; - } - LL_DEBUGS("Avatar") << "linking item " << item_id << " name " << item->getName() << " to " << mDstCatID << llendl; - // create an inventory item link. - if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate")) - { - LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << llendl; - return true; - } - link_inventory_item(gAgent.getID(), - item->getLinkedUUID(), - mDstCatID, - item->getName(), - item->getActualDescription(), - LLAssetType::AT_LINK, - new LLBoostFuncInventoryCallback( - boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer()))); - return true; - } - else - { - // create a base outfit link if appropriate. - LLViewerInventoryCategory *catp = gInventory.getCategory(item_id); - if (!catp) - { - llwarns << "link request failed, id not found as inventory item or category " << item_id << llendl; - return false; - } - const LLUUID cof = LLAppearanceMgr::instance().getCOF(); - std::string new_outfit_name = ""; - - LLAppearanceMgr::instance().purgeBaseOutfitLink(cof); - - if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) - { - if (ll_frand() < gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate")) - { - LL_DEBUGS("Avatar") << "simulating failure by not sending request for item " << item_id << llendl; - return true; - } - LL_DEBUGS("Avatar") << "linking folder " << item_id << " name " << catp->getName() << " to cof " << cof << llendl; - link_inventory_item(gAgent.getID(), item_id, cof, catp->getName(), "", - LLAssetType::AT_LINK_FOLDER, - new LLBoostFuncInventoryCallback( - boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item_id,_1,LLTimer()))); - new_outfit_name = catp->getName(); - request_sent = true; - } - - LLAppearanceMgr::instance().updatePanelOutfitName(new_outfit_name); - } - return request_sent; - } -}; - LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit_ordering, bool enforce_item_restrictions): mFireCount(0), @@ -533,6 +453,32 @@ void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item) mFireCount++; } +LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id): + mItemID(item_id) +{ +} + +LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOnDestroy() +{ + LLAppearanceMgr::instance().updateAppearanceFromCOF(); + + // Start editing the item if previously requested. + gAgentWearables.editWearableIfRequested(mItemID); + + // TODO: camera mode may not be changed if a debug setting is tweaked + if( gAgentCamera.cameraCustomizeAvatar() ) + { + // If we're in appearance editing mode, the current tab may need to be refreshed + LLSidepanelAppearance *panel = dynamic_cast( + LLFloaterSidePanelContainer::getPanel("appearance")); + if (panel) + { + panel->showDefaultSubpart(); + } + } +} + + struct LLFoundData { LLFoundData() : @@ -1272,8 +1218,12 @@ void wear_on_avatar_cb(const LLUUID& inv_item, bool do_replace = false) } } -bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_update, bool replace, LLPointer cb) +bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, + bool do_update, + bool replace, + LLPointer cb) { + if (item_id_to_wear.isNull()) return false; // *TODO: issue with multi-wearable should be fixed: @@ -1320,7 +1270,11 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up { removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1)); } - addCOFItemLink(item_to_wear, do_update, cb); + if (!cb && do_update) + { + cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear); + } + addCOFItemLink(item_to_wear, cb); } break; case LLAssetType::AT_BODYPART: @@ -1329,8 +1283,11 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, bool do_up // Remove the existing wearables of the same type. // Remove existing body parts anyway because we must not be able to wear e.g. two skins. removeCOFLinksOfType(item_to_wear->getWearableType()); - - addCOFItemLink(item_to_wear, do_update, cb); + if (!cb && do_update) + { + cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear); + } + addCOFItemLink(item_to_wear, cb); break; case LLAssetType::AT_OBJECT: rez_attachment(item_to_wear, NULL, replace); @@ -1640,7 +1597,7 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) return items.size() > 0; } -void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) +void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer cb) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -1656,7 +1613,7 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category) LLViewerInventoryCategory* catp = item->getLinkedCategory(); if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) { - gInventory.purgeObject(item->getUUID()); + remove_inventory_item(item->getUUID(), cb); } } } @@ -1843,7 +1800,7 @@ void LLAppearanceMgr::createBaseOutfitLink(const LLUUID& category, LLPointergetPreferredType() == LLFolderType::FT_OUTFIT) { @@ -2339,9 +2296,8 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor class LLDeferredCOFLinkObserver: public LLInventoryObserver { public: - LLDeferredCOFLinkObserver(const LLUUID& item_id, bool do_update, LLPointer cb = NULL, std::string description = ""): + LLDeferredCOFLinkObserver(const LLUUID& item_id, LLPointer cb = NULL, std::string description = ""): mItemID(item_id), - mDoUpdate(do_update), mCallback(cb), mDescription(description) { @@ -2357,14 +2313,13 @@ public: if (item) { gInventory.removeObserver(this); - LLAppearanceMgr::instance().addCOFItemLink(item,mDoUpdate,mCallback); + LLAppearanceMgr::instance().addCOFItemLink(item, mCallback); delete this; } } private: const LLUUID mItemID; - bool mDoUpdate; std::string mDescription; LLPointer mCallback; }; @@ -2372,42 +2327,26 @@ private: // BAP - note that this runs asynchronously if the item is not already loaded from inventory. // Dangerous if caller assumes link will exist after calling the function. -void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, bool do_update, LLPointer cb, const std::string description) +void LLAppearanceMgr::addCOFItemLink(const LLUUID &item_id, + LLPointer cb, + const std::string description) { const LLInventoryItem *item = gInventory.getItem(item_id); if (!item) { - LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, do_update, cb, description); + LLDeferredCOFLinkObserver *observer = new LLDeferredCOFLinkObserver(item_id, cb, description); gInventory.addObserver(observer); } else { - addCOFItemLink(item, do_update, cb, description); + addCOFItemLink(item, cb, description); } } -void modified_cof_cb(const LLUUID& inv_item) -{ - LLAppearanceMgr::instance().updateAppearanceFromCOF(); - - // Start editing the item if previously requested. - gAgentWearables.editWearableIfRequested(inv_item); - - // TODO: camera mode may not be changed if a debug setting is tweaked - if( gAgentCamera.cameraCustomizeAvatar() ) - { - // If we're in appearance editing mode, the current tab may need to be refreshed - LLSidepanelAppearance *panel = dynamic_cast(LLFloaterSidePanelContainer::getPanel("appearance")); - if (panel) - { - panel->showDefaultSubpart(); - } - } -} - -void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update, LLPointer cb, const std::string description) +void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, + LLPointer cb, + const std::string description) { - std::string link_description = description; const LLViewerInventoryItem *vitem = dynamic_cast(item); if (!vitem) { @@ -2447,30 +2386,19 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update ++count; if (is_body_part && inv_item->getIsLinkType() && (vitem->getWearableType() == wearable_type)) { - gInventory.purgeObject(inv_item->getUUID()); + remove_inventory_item(inv_item->getUUID(), cb); } else if (count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) { // MULTI-WEARABLES: make sure we don't go over MAX_CLOTHING_PER_TYPE - gInventory.purgeObject(inv_item->getUUID()); + remove_inventory_item(inv_item->getUUID(), cb); } } } - if (linked_already) + if (!linked_already) { - if (do_update) - { - LLAppearanceMgr::updateAppearanceFromCOF(); - } - return; - } - else - { - if(do_update && cb.isNull()) - { - cb = new LLBoostFuncInventoryCallback(modified_cof_cb); - } + std::string link_description = description; if (vitem->getIsLinkType()) { link_description = vitem->getActualDescription(); @@ -2483,7 +2411,6 @@ void LLAppearanceMgr::addCOFItemLink(const LLInventoryItem *item, bool do_update LLAssetType::AT_LINK, cb); } - return; } LLInventoryModel::item_array_t LLAppearanceMgr::findCOFItemLinks(const LLUUID& item_id) @@ -2567,7 +2494,7 @@ void LLAppearanceMgr::removeAllAttachmentsFromAvatar() removeItemsFromAvatar(ids_to_remove); } -void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id) +void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id, LLPointer cb) { gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); @@ -2582,12 +2509,12 @@ void LLAppearanceMgr::removeCOFItemLinks(const LLUUID& item_id) const LLInventoryItem* item = item_array.get(i).get(); if (item->getIsLinkType() && item->getLinkedUUID() == item_id) { - gInventory.purgeObject(item->getUUID()); + remove_inventory_item(item->getUUID(), cb); } } } -void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type) +void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type, LLPointer cb) { LLFindWearablesOfType filter_wearables_of_type(type); LLInventoryModel::cat_array_t cats; @@ -2600,7 +2527,7 @@ void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type) const LLViewerInventoryItem* item = *it; if (item->getIsLinkType()) // we must operate on links only { - gInventory.purgeObject(item->getUUID()); + remove_inventory_item(item->getUUID(), cb); } } } @@ -3550,7 +3477,7 @@ void LLAppearanceMgr::registerAttachment(const LLUUID& item_id) // we have to pass do_update = true to call LLAppearanceMgr::updateAppearanceFromCOF. // it will trigger gAgentWariables.notifyLoadingFinished() // But it is not acceptable solution. See EXT-7777 - LLAppearanceMgr::addCOFItemLink(item_id, false); // Add COF link for item. + LLAppearanceMgr::addCOFItemLink(item_id); // Add COF link for item. } else { @@ -3586,8 +3513,8 @@ bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), cats, items, - LLInventoryModel::EXCLUDE_TRASH, - find_links); + LLInventoryModel::EXCLUDE_TRASH, + find_links); return !items.empty(); } diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 0cc06ab210..2cc76c4b4c 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -107,12 +107,13 @@ public: const LLUUID getBaseOutfitUUID(); // Wear/attach an item (from a user's inventory) on the agent - bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update = true, bool replace = false, LLPointer cb = NULL); + bool wearItemOnAvatar(const LLUUID& item_to_wear, bool do_update, bool replace = false, + LLPointer cb = NULL); // Update the displayed outfit name in UI. void updatePanelOutfitName(const std::string& name); - void purgeBaseOutfitLink(const LLUUID& category); + void purgeBaseOutfitLink(const LLUUID& category, LLPointer cb = NULL); void createBaseOutfitLink(const LLUUID& category, LLPointer link_waiter); void updateAgentWearables(LLWearableHoldingPattern* holder, bool append); @@ -136,15 +137,15 @@ public: LLPointer cb); // Add COF link to individual item. - void addCOFItemLink(const LLUUID& item_id, bool do_update = true, LLPointer cb = NULL, const std::string description = ""); - void addCOFItemLink(const LLInventoryItem *item, bool do_update = true, LLPointer cb = NULL, const std::string description = ""); + void addCOFItemLink(const LLUUID& item_id, LLPointer cb = NULL, const std::string description = ""); + void addCOFItemLink(const LLInventoryItem *item, LLPointer cb = NULL, const std::string description = ""); // Find COF entries referencing the given item. LLInventoryModel::item_array_t findCOFItemLinks(const LLUUID& item_id); // Remove COF entries - void removeCOFItemLinks(const LLUUID& item_id); - void removeCOFLinksOfType(LLWearableType::EType type); + void removeCOFItemLinks(const LLUUID& item_id, LLPointer cb = NULL); + void removeCOFLinksOfType(LLWearableType::EType type, LLPointer cb = NULL); void removeAllClothesFromAvatar(); void removeAllAttachmentsFromAvatar(); @@ -272,6 +273,20 @@ private: bool mEnforceItemRestrictions; }; +class LLUpdateAppearanceAndEditWearableOnDestroy: public LLInventoryCallback +{ +public: + LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id); + + /* virtual */ void fire(const LLUUID& item_id) {} + + ~LLUpdateAppearanceAndEditWearableOnDestroy(); + +private: + LLUUID mItemID; +}; + +class #define SUPPORT_ENSEMBLES 0 diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index 56051ff684..def4d40f9f 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -619,7 +619,7 @@ void LLFloaterGesture::addToCurrentOutFit() LLAppearanceMgr* am = LLAppearanceMgr::getInstance(); for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++) { - am->addCOFItemLink(*it); + am->addCOFItemLink(*it, new LLUpdateAppearanceAndEditWearableOnDestroy(*it)); } } diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index c09d4393c8..0e3057dcad 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -1184,12 +1184,12 @@ BOOL LLPanelOutfitEdit::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, * second argument is used to delay the appearance update until all dragged items * are added to optimize user experience. */ - LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), false); + LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID()); } else { // if asset id is not available for the item we must wear it immediately (attachments only) - LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), true); + LLAppearanceMgr::instance().addCOFItemLink(item->getLinkedUUID(), new LLUpdateAppearanceAndEditWearableOnDestroy(item->getUUID())); } } diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h index 7cb62efb47..6b0e8ed4ef 100755 --- a/indra/newview/llviewerinventory.h +++ b/indra/newview/llviewerinventory.h @@ -274,7 +274,7 @@ class LLBoostFuncInventoryCallback: public LLInventoryCallback { public: - LLBoostFuncInventoryCallback(inventory_func_type fire_func, + LLBoostFuncInventoryCallback(inventory_func_type fire_func = no_op_inventory_func, nullary_func_type destroy_func = no_op): mFireFunc(fire_func), mDestroyFunc(destroy_func) -- cgit v1.2.3 From 4967998a5c10abcc64e097a4e95505f9adbe4de7 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 24 Apr 2013 13:27:04 -0400 Subject: CHUI-849 WIP, SH-4116 WIP - added simpler match check in inventory for when we don't need the list of matches to be returned. --- indra/newview/llappearancemgr.cpp | 61 +++++++++----------------------------- indra/newview/llinventorymodel.cpp | 59 ++++++++++++++++++++++++++++++------ indra/newview/llinventorymodel.h | 3 ++ 3 files changed, 67 insertions(+), 56 deletions(-) mode change 100644 => 100755 indra/newview/llinventorymodel.h (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 634f5d1389..5a9901f12d 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1541,15 +1541,8 @@ bool LLAppearanceMgr::getCanRemoveOutfit(const LLUUID& outfit_cat_id) // static bool LLAppearanceMgr::getCanRemoveFromCOF(const LLUUID& outfit_cat_id) { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; LLFindWearablesEx is_worn(/*is_worn=*/ true, /*include_body_parts=*/ false); - gInventory.collectDescendentsIf(outfit_cat_id, - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - is_worn); - return items.size() > 0; + return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn); } // static @@ -1560,15 +1553,8 @@ bool LLAppearanceMgr::getCanAddToCOF(const LLUUID& outfit_cat_id) return false; } - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); - gInventory.collectDescendentsIf(outfit_cat_id, - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - not_worn); - return items.size() > 0; + return gInventory.hasMatchingDirectDescendent(outfit_cat_id, not_worn); } bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) @@ -1586,15 +1572,8 @@ bool LLAppearanceMgr::getCanReplaceCOF(const LLUUID& outfit_cat_id) } // Check whether the outfit contains any wearables we aren't wearing already (STORM-702). - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; LLFindWearablesEx is_worn(/*is_worn=*/ false, /*include_body_parts=*/ true); - gInventory.collectDescendentsIf(outfit_cat_id, - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - is_worn); - return items.size() > 0; + return gInventory.hasMatchingDirectDescendent(outfit_cat_id, is_worn); } void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointer cb) @@ -2243,6 +2222,7 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego LLAppearanceMgr::changeOutfit(TRUE, category->getUUID(), append); } +// FIXME do we really want to search entire inventory for matching name? void LLAppearanceMgr::wearOutfitByName(const std::string& name) { LL_INFOS("Avatar") << self_av_string() << "Wearing category " << name << LL_ENDL; @@ -3501,22 +3481,21 @@ void LLAppearanceMgr::unregisterAttachment(const LLUUID& item_id) BOOL LLAppearanceMgr::getIsInCOF(const LLUUID& obj_id) const { - return gInventory.isObjectDescendentOf(obj_id, getCOF()); + const LLUUID& cof = getCOF(); + if (obj_id == cof) + return TRUE; + const LLInventoryObject* obj = gInventory.getObject(obj_id); + if (obj && obj->getParentUUID() == cof) + return TRUE; + return FALSE; } // static bool LLAppearanceMgr::isLinkInCOF(const LLUUID& obj_id) { - LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; - LLLinkedItemIDMatches find_links(gInventory.getLinkedItemID(obj_id)); - gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), - cats, - items, - LLInventoryModel::EXCLUDE_TRASH, - find_links); - - return !items.empty(); + const LLUUID& target_id = gInventory.getLinkedItemID(obj_id); + LLLinkedItemIDMatches find_links(target_id); + return gInventory.hasMatchingDirectDescendent(LLAppearanceMgr::instance().getCOF(), find_links); } BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const @@ -3533,18 +3512,6 @@ BOOL LLAppearanceMgr::getIsProtectedCOFItem(const LLUUID& obj_id) const // For now, don't allow direct deletion from the COF. Instead, force users // to choose "Detach" or "Take Off". return TRUE; - /* - const LLInventoryObject *obj = gInventory.getObject(obj_id); - if (!obj) return FALSE; - - // Can't delete bodyparts, since this would be equivalent to removing the item. - if (obj->getType() == LLAssetType::AT_BODYPART) return TRUE; - - // Can't delete the folder link, since this is saved for bookkeeping. - if (obj->getActualType() == LLAssetType::AT_LINK_FOLDER) return TRUE; - - return FALSE; - */ } class CallAfterCategoryFetchStage2: public LLInventoryFetchItemsObserver diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index bbf284147a..11223d96b6 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -593,6 +593,40 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id, return id; } +// This is optimized for the case that we just want to know whether a +// category has any immediate children meeting a condition, without +// needing to recurse or build up any lists. +bool LLInventoryModel::hasMatchingDirectDescendent(const LLUUID& cat_id, + LLInventoryCollectFunctor& filter) +{ + LLInventoryModel::cat_array_t *cats; + LLInventoryModel::item_array_t *items; + getDirectDescendentsOf(cat_id, cats, items); + if (cats) + { + for (LLInventoryModel::cat_array_t::const_iterator it = cats->begin(); + it != cats->end(); ++it) + { + if (filter(*it,NULL)) + { + return true; + } + } + } + if (items) + { + for (LLInventoryModel::item_array_t::const_iterator it = items->begin(); + it != items->end(); ++it) + { + if (filter(NULL,*it)) + { + return true; + } + } + } + return false; +} + // Starting with the object specified, add it's descendents to the // array provided, but do not add the inventory object specified by // id. There is no guaranteed order. Neither array will be erased @@ -723,6 +757,10 @@ LLInventoryModel::item_array_t LLInventoryModel::collectLinkedItems(const LLUUID const LLUUID& start_folder_id) { item_array_t items; + const LLInventoryObject *obj = getObject(id); + if (!obj || obj->getIsLinkType()) + return items; + LLInventoryModel::cat_array_t cat_array; LLLinkedItemIDMatches is_linked_item_match(id); collectDescendentsIf((start_folder_id == LLUUID::null ? gInventory.getRootFolderID() : start_folder_id), @@ -1170,17 +1208,20 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) // REBUILD is expensive, so clear the current change list first else // everything else on the changelist will also get rebuilt. - gInventory.notifyObservers(); - for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); - iter != item_array.end(); - iter++) + if (item_array.size()) { - const LLViewerInventoryItem *linked_item = (*iter); - const LLUUID &item_id = linked_item->getUUID(); - if (item_id == baseobj_id) continue; - addChangedMask(LLInventoryObserver::REBUILD, item_id); + gInventory.notifyObservers(); + for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); + iter != item_array.end(); + iter++) + { + const LLViewerInventoryItem *linked_item = (*iter); + const LLUUID &item_id = linked_item->getUUID(); + if (item_id == baseobj_id) continue; + addChangedMask(LLInventoryObserver::REBUILD, item_id); + } + gInventory.notifyObservers(); } - gInventory.notifyObservers(); } // This is a method which collects the descendents of the id diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h old mode 100644 new mode 100755 index 0b017b7514..50b57ea08d --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -205,6 +205,9 @@ public: EXCLUDE_TRASH = FALSE, INCLUDE_TRASH = TRUE }; + // Simpler existence test if matches don't actually need to be collected. + bool hasMatchingDirectDescendent(const LLUUID& cat_id, + LLInventoryCollectFunctor& filter); void collectDescendents(const LLUUID& id, cat_array_t& categories, item_array_t& items, -- cgit v1.2.3 From a9fa707a7da9977914db8527f15b59bb6a4bc6b7 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 24 Apr 2013 16:09:33 -0400 Subject: SH-4128 - more cleanup of COF-link manipulating functions --- indra/newview/llappearancemgr.cpp | 60 +++++++++++++++++++------------------- indra/newview/llfloatergesture.cpp | 3 +- 2 files changed, 32 insertions(+), 31 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5a9901f12d..792220c385 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -430,6 +430,16 @@ LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy(bool update_base_outfit selfStartPhase("update_appearance_on_destroy"); } +void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item) +{ + LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item); + const std::string item_name = item ? item->getName() : "ITEM NOT FOUND"; +#ifndef LL_RELEASE_FOR_DOWNLOAD + LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL; +#endif + mFireCount++; +} + LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() { if (!LLApp::isExiting()) @@ -443,16 +453,6 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() } } -void LLUpdateAppearanceOnDestroy::fire(const LLUUID& inv_item) -{ - LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(inv_item); - const std::string item_name = item ? item->getName() : "ITEM NOT FOUND"; -#ifndef LL_RELEASE_FOR_DOWNLOAD - LL_DEBUGS("Avatar") << self_av_string() << "callback fired [ name:" << item_name << " UUID:" << inv_item << " count:" << mFireCount << " ] " << LL_ENDL; -#endif - mFireCount++; -} - LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnDestroy(const LLUUID& item_id): mItemID(item_id) { @@ -460,20 +460,23 @@ LLUpdateAppearanceAndEditWearableOnDestroy::LLUpdateAppearanceAndEditWearableOnD LLUpdateAppearanceAndEditWearableOnDestroy::~LLUpdateAppearanceAndEditWearableOnDestroy() { - LLAppearanceMgr::instance().updateAppearanceFromCOF(); - - // Start editing the item if previously requested. - gAgentWearables.editWearableIfRequested(mItemID); - - // TODO: camera mode may not be changed if a debug setting is tweaked - if( gAgentCamera.cameraCustomizeAvatar() ) + if (!LLApp::isExiting()) { - // If we're in appearance editing mode, the current tab may need to be refreshed - LLSidepanelAppearance *panel = dynamic_cast( - LLFloaterSidePanelContainer::getPanel("appearance")); - if (panel) + LLAppearanceMgr::instance().updateAppearanceFromCOF(); + + // Start editing the item if previously requested. + gAgentWearables.editWearableIfRequested(mItemID); + + // TODO: camera mode may not be changed if a debug setting is tweaked + if( gAgentCamera.cameraCustomizeAvatar() ) { - panel->showDefaultSubpart(); + // If we're in appearance editing mode, the current tab may need to be refreshed + LLSidepanelAppearance *panel = dynamic_cast( + LLFloaterSidePanelContainer::getPanel("appearance")); + if (panel) + { + panel->showDefaultSubpart(); + } } } } @@ -1587,13 +1590,10 @@ void LLAppearanceMgr::purgeBaseOutfitLink(const LLUUID& category, LLPointergetActualType() != LLAssetType::AT_LINK_FOLDER) continue; - if (item->getIsLinkType()) + LLViewerInventoryCategory* catp = item->getLinkedCategory(); + if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) { - LLViewerInventoryCategory* catp = item->getLinkedCategory(); - if(catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) - { - remove_inventory_item(item->getUUID(), cb); - } + remove_inventory_item(item->getUUID(), cb); } } } @@ -2276,7 +2276,7 @@ bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventor class LLDeferredCOFLinkObserver: public LLInventoryObserver { public: - LLDeferredCOFLinkObserver(const LLUUID& item_id, LLPointer cb = NULL, std::string description = ""): + LLDeferredCOFLinkObserver(const LLUUID& item_id, LLPointer cb, const std::string& description): mItemID(item_id), mCallback(cb), mDescription(description) @@ -2293,7 +2293,7 @@ public: if (item) { gInventory.removeObserver(this); - LLAppearanceMgr::instance().addCOFItemLink(item, mCallback); + LLAppearanceMgr::instance().addCOFItemLink(item, mCallback, mDescription); delete this; } } diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index def4d40f9f..af5c11e12c 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -617,9 +617,10 @@ void LLFloaterGesture::addToCurrentOutFit() uuid_vec_t ids; getSelectedIds(ids); LLAppearanceMgr* am = LLAppearanceMgr::getInstance(); + LLPointer cb = new LLUpdateAppearanceOnDestroy; for(uuid_vec_t::const_iterator it = ids.begin(); it != ids.end(); it++) { - am->addCOFItemLink(*it, new LLUpdateAppearanceAndEditWearableOnDestroy(*it)); + am->addCOFItemLink(*it, cb); } } -- cgit v1.2.3 From eb88e4d37850a48132193d332fa8945d3932369b Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 24 Apr 2013 18:08:20 -0400 Subject: SH-4128 WIP - cleanup around item link removal and callbacks --- indra/newview/llappearancemgr.cpp | 24 ++++++++++++++---------- indra/newview/llgesturemgr.cpp | 13 ++++++++++--- indra/newview/llinventorymodel.cpp | 5 +++-- indra/newview/llpaneleditwearable.cpp | 23 ++++++++++++++++++----- 4 files changed, 45 insertions(+), 20 deletions(-) mode change 100644 => 100755 indra/newview/llgesturemgr.cpp mode change 100644 => 100755 indra/newview/llpaneleditwearable.cpp (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 792220c385..399cea676c 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1265,18 +1265,21 @@ bool LLAppearanceMgr::wearItemOnAvatar(const LLUUID& item_id_to_wear, switch (item_to_wear->getType()) { case LLAssetType::AT_CLOTHING: - if (gAgentWearables.areWearablesLoaded()) + if (gAgentWearables.areWearablesLoaded()) { + if (!cb && do_update) + { + cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear); + } S32 wearable_count = gAgentWearables.getWearableCount(item_to_wear->getWearableType()); if ((replace && wearable_count != 0) || (wearable_count >= LLAgentWearables::MAX_CLOTHING_PER_TYPE) ) { - removeCOFItemLinks(gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), wearable_count-1)); - } - if (!cb && do_update) - { - cb = new LLUpdateAppearanceAndEditWearableOnDestroy(item_id_to_wear); + LLUUID item_id = gAgentWearables.getWearableItemID(item_to_wear->getWearableType(), + wearable_count-1); + removeCOFItemLinks(item_id, cb); } + addCOFItemLink(item_to_wear, cb); } break; @@ -3284,21 +3287,22 @@ void LLAppearanceMgr::removeItemsFromAvatar(const uuid_vec_t& ids_to_remove) if (ids_to_remove.empty()) { llwarns << "called with empty list, nothing to do" << llendl; + return; } + LLPointer cb = new LLUpdateAppearanceOnDestroy; for (uuid_vec_t::const_iterator it = ids_to_remove.begin(); it != ids_to_remove.end(); ++it) { const LLUUID& id_to_remove = *it; const LLUUID& linked_item_id = gInventory.getLinkedItemID(id_to_remove); - removeCOFItemLinks(linked_item_id); + removeCOFItemLinks(linked_item_id, cb); } - updateAppearanceFromCOF(); } void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove) { LLUUID linked_item_id = gInventory.getLinkedItemID(id_to_remove); - removeCOFItemLinks(linked_item_id); - updateAppearanceFromCOF(); + LLPointer cb = new LLUpdateAppearanceOnDestroy; + removeCOFItemLinks(linked_item_id, cb); } bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body) diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp old mode 100644 new mode 100755 index 9aa86297fc..5eaa83d872 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -299,6 +299,12 @@ void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, } +void notify_update_label(const LLUUID& base_item_id) +{ + gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id); + LLGestureMgr::instance().notifyObservers(); +} + void LLGestureMgr::deactivateGesture(const LLUUID& item_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); @@ -322,7 +328,6 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) } mActive.erase(it); - gInventory.addChangedMask(LLInventoryObserver::LABEL, base_item_id); // Inform the database of this change LLMessageSystem* msg = gMessageSystem; @@ -338,9 +343,11 @@ void LLGestureMgr::deactivateGesture(const LLUUID& item_id) gAgent.sendReliableMessage(); - LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id); + LLPointer cb = + new LLBoostFuncInventoryCallback(no_op_inventory_func, + boost::bind(notify_update_label,base_item_id)); - notifyObservers(); + LLAppearanceMgr::instance().removeCOFItemLinks(base_item_id, cb); } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 11223d96b6..bc327b8359 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1178,10 +1178,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id) mParentChildCategoryTree.erase(id); } addChangedMask(LLInventoryObserver::REMOVE, id); - bool is_link_type = obj->getIsLinkType(); obj = NULL; // delete obj + // Can't have links to links, so there's no need for this update // if the item removed is a link. + bool is_link_type = obj->getIsLinkType(); if (!is_link_type) { updateLinkedObjectsFromPurge(id); @@ -1208,7 +1209,7 @@ void LLInventoryModel::updateLinkedObjectsFromPurge(const LLUUID &baseobj_id) // REBUILD is expensive, so clear the current change list first else // everything else on the changelist will also get rebuilt. - if (item_array.size()) + if (item_array.size() > 0) { gInventory.notifyObservers(); for (LLInventoryModel::item_array_t::const_iterator iter = item_array.begin(); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp old mode 100644 new mode 100755 index e71dba5cae..06c923273b --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1079,10 +1079,15 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) if (force_save_as) { - // the name of the wearable has changed, re-save wearable with new name - LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID()); + // FIXME race condition if removeCOFItemLinks does not + // complete immediately. Looks like we're counting on the + // fact that updateAppearanceFromCOF will get called after + // we exit customize mode. + + // the name of the wearable has changed, re-save wearable with new name + LLAppearanceMgr::instance().removeCOFItemLinks(mWearablePtr->getItemID()); gAgentWearables.saveWearableAs(mWearablePtr->getType(), index, new_name, description, FALSE); - mNameEditor->setText(mWearableItem->getName()); + mNameEditor->setText(mWearableItem->getName()); } else { @@ -1091,6 +1096,14 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) // version so texture baking service knows appearance has changed. if (link_item) { + // FIXME - two link-modifying calls here plus one + // inventory change request, none of which use a + // callback. When does a new appearance request go out + // and how is it synced with these changes? As above, + // we seem to be implicitly depending on + // updateAppearanceFromCOF() to be called when we + // exit customize mode. + // Create new link link_inventory_item( gAgent.getID(), link_item->getLinkedUUID(), @@ -1100,9 +1113,9 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) LLAssetType::AT_LINK, NULL); // Remove old link - gInventory.purgeObject(link_item->getUUID()); + remove_inventory_item(link_item->getUUID()); } - gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); + gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); } -- cgit v1.2.3 From d73588eaddb1ada6ac896850c3aa9d25307e076a Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 24 Apr 2013 18:38:40 -0400 Subject: SH-4128 WIP - misc cleanup --- indra/newview/llinventorymodel.cpp | 4 ++-- indra/newview/llpaneleditwearable.cpp | 2 +- indra/newview/llviewerinventory.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index bc327b8359..a0b9e7b0ec 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1178,11 +1178,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id) mParentChildCategoryTree.erase(id); } addChangedMask(LLInventoryObserver::REMOVE, id); - obj = NULL; // delete obj - + // Can't have links to links, so there's no need for this update // if the item removed is a link. bool is_link_type = obj->getIsLinkType(); + obj = NULL; // delete obj if (!is_link_type) { updateLinkedObjectsFromPurge(id); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 06c923273b..580e31591c 100755 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1113,7 +1113,7 @@ void LLPanelEditWearable::saveChanges(bool force_save_as) LLAssetType::AT_LINK, NULL); // Remove old link - remove_inventory_item(link_item->getUUID()); + remove_inventory_item(link_item->getUUID(), NULL); } gAgentWearables.saveWearable(mWearablePtr->getType(), index, TRUE, new_name); } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 316fca7769..06efeb86d9 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -1276,7 +1276,7 @@ void remove_inventory_item( } else { - llwarns << "remove_inventory_item called for nonexistent item " << item_id << llendl; + llwarns << "remove_inventory_item called for invalid or nonexistent item " << item_id << llendl; } } -- cgit v1.2.3