From 0ca3c5c7fdd6790d98259fc6d8459633896ce7a0 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 12 Apr 2016 12:08:59 -0700 Subject: Added exponential timeout to retry, protect against attempting to downgrade the COF version in the bake request. --- indra/newview/llappearancemgr.cpp | 131 +++++++++++++++++++++++--------------- indra/newview/llappearancemgr.h | 2 + 2 files changed, 83 insertions(+), 50 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 99dcb80a4a..df56d7403c 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -65,7 +65,12 @@ #pragma warning (disable:4702) #endif -#if 1 +namespace +{ + const S32 BAKE_RETRY_MAX_COUNT = 5; + const F32 BAKE_RETRY_TIMEOUT = 2.0F; +} + // *TODO$: LLInventoryCallback should be deprecated to conform to the new boost::bind/coroutine model. // temp code in transition void doAppearanceCb(LLPointer cb, LLUUID id) @@ -73,8 +78,6 @@ void doAppearanceCb(LLPointer cb, LLUUID id) if (cb.notNull()) cb->fire(id); } -#endif - std::string self_av_string() { @@ -3354,12 +3357,21 @@ LLSD LLAppearanceMgr::dumpCOF() const void LLAppearanceMgr::requestServerAppearanceUpdate() { - LLCoprocedureManager::CoProcedure_t proc = boost::bind(&LLAppearanceMgr::serverAppearanceUpdateCoro, this, _1); - LLCoprocedureManager::instance().enqueueCoprocedure("AIS", "LLAppearanceMgr::serverAppearanceUpdateCoro", proc); + if (!mOutstandingAppearanceBakeRequest) + { + mRerequestAppearanceBake = false; + LLCoprocedureManager::CoProcedure_t proc = boost::bind(&LLAppearanceMgr::serverAppearanceUpdateCoro, this, _1); + LLCoprocedureManager::instance().enqueueCoprocedure("AIS", "LLAppearanceMgr::serverAppearanceUpdateCoro", proc); + } + else + { + mRerequestAppearanceBake = true; + } } void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter) { + mRerequestAppearanceBake = false; if (!gAgent.getRegion()) { LL_WARNS("Avatar") << "Region not set, cannot request server appearance update" << LL_ENDL; @@ -3386,57 +3398,57 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd return; } -#if 0 - static int reqcount = 0; - int r_count = ++reqcount; - LL_WARNS("Avatar") << "START: Server Bake request #" << r_count << "!" << LL_ENDL; -#endif - - // If we have already received an update for this or higher cof version, - // put a warning in the log but request anyway. - S32 cofVersion = getCOFVersion(); - S32 lastRcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion; - S32 lastReq = gAgentAvatarp->mLastUpdateRequestCOFVersion; - - LL_INFOS("Avatar") << "Requesting COF version " << cofVersion << - " (Last Received:" << lastRcv << ")" << - " (Last Requested:" << lastReq << ")" << LL_ENDL; - - if ((cofVersion != LLViewerInventoryCategory::VERSION_UNKNOWN)) + llcoro::suspend(); + S32 retryCount(0); + bool bRetry; + do { - if (cofVersion < lastRcv) + BoolSetter outstanding(mOutstandingAppearanceBakeRequest); + + // If we have already received an update for this or higher cof version, + // put a warning in the log and cancel the request. + S32 cofVersion = getCOFVersion(); + S32 lastRcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion; + S32 lastReq = gAgentAvatarp->mLastUpdateRequestCOFVersion; + + LL_INFOS("Avatar") << "Requesting COF version " << cofVersion << + " (Last Received:" << lastRcv << ")" << + " (Last Requested:" << lastReq << ")" << LL_ENDL; + + if (cofVersion == LLViewerInventoryCategory::VERSION_UNKNOWN) { - LL_WARNS("Avatar") << "Have already received update for cof version " << lastRcv - << " but requesting for " << cofVersion << LL_ENDL; + LL_WARNS("AVatar") << "COF version is unknown... not requesting until COF version is known." << LL_ENDL; + return; } - if (lastReq > cofVersion) + else { - LL_WARNS("Avatar") << "Request already in flight for cof version " << lastReq - << " but requesting for " << cofVersion << LL_ENDL; + if (cofVersion < lastRcv) + { + LL_WARNS("Avatar") << "Have already received update for cof version " << lastRcv + << " but requesting for " << cofVersion << LL_ENDL; + return; + } + if (lastReq > cofVersion) + { + LL_WARNS("Avatar") << "Request already in flight for cof version " << lastReq + << " but requesting for " << cofVersion << LL_ENDL; + return; + } } - } - - // Actually send the request. - LL_DEBUGS("Avatar") << "Will send request for cof_version " << cofVersion << LL_ENDL; -// LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter( -// "UpdateAvatarAppearance", gAgent.getAgentPolicy())); + // Actually send the request. + LL_DEBUGS("Avatar") << "Will send request for cof_version " << cofVersion << LL_ENDL; - bool bRetry; - do - { bRetry = false; LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); - S32 reqCofVersion = getCOFVersion(); // Treat COF version (gets set by AISAPI as authoritative, - // not what the bake request tells us to use). if (gSavedSettings.getBOOL("DebugForceAppearanceRequestFailure")) { - reqCofVersion += 999; + cofVersion += 999; LL_WARNS("Avatar") << "Forcing version failure on COF Baking" << LL_ENDL; } - LL_INFOS() << "Requesting bake for COF version " << reqCofVersion << LL_ENDL; + LL_INFOS() << "Requesting bake for COF version " << cofVersion << LL_ENDL; LLSD postData; if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate")) @@ -3445,10 +3457,10 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd } else { - postData["cof_version"] = reqCofVersion; + postData["cof_version"] = cofVersion; } - gAgentAvatarp->mLastUpdateRequestCOFVersion = reqCofVersion; + gAgentAvatarp->mLastUpdateRequestCOFVersion = cofVersion; LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); @@ -3466,14 +3478,30 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd // on multiple machines. if (result.has("expected")) { + S32 expectedCofVersion = result["expected"].asInteger(); + LL_WARNS("Avatar") << "Server expected " << expectedCofVersion << " as COF version" << LL_ENDL; + bRetry = true; // Wait for a 1/2 second before trying again. Just to keep from asking too quickly. - llcoro::suspendUntilTimeout(0.5); + if (++retryCount > BAKE_RETRY_MAX_COUNT) + { + LL_WARNS("Avatar") << "Bake retry count exceeded!" << LL_ENDL; + break; + } + F32 timeout = pow(BAKE_RETRY_TIMEOUT, static_cast(retryCount)) - 1.0; - LL_WARNS("Avatar") << "Server expected " << expectedCofVersion << " as COF version" << LL_ENDL; + LL_WARNS("Avatar") << "Bake retry #" << retryCount << " in " << timeout << " seconds." << LL_ENDL; + + llcoro::suspendUntilTimeout(timeout); + bRetry = true; continue; } + else + { + LL_WARNS("Avatar") << "No retry attempted." << LL_ENDL; + break; + } } LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL; @@ -3484,10 +3512,11 @@ void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAd } while (bRetry); -#if 0 - LL_WARNS("Avatar") << "END: Server Bake request #" << r_count << "!" << LL_ENDL; -#endif - + if (mRerequestAppearanceBake) + { // A bake request came in while this one was still outstanding. + // Requeue ourself for a later request. + requestServerAppearanceUpdate(); + } } /*static*/ @@ -3855,7 +3884,9 @@ LLAppearanceMgr::LLAppearanceMgr(): mOutfitLocked(false), mInFlightCounter(0), mInFlightTimer(), - mIsInUpdateAppearanceFromCOF(false) + mIsInUpdateAppearanceFromCOF(false), + mOutstandingAppearanceBakeRequest(false), + mRerequestAppearanceBake(false) { LLOutfitObserver& outfit_observer = LLOutfitObserver::instance(); // unlock outfit on save operation completed diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index b97f9018c0..74024abf67 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -255,6 +255,8 @@ private: bool mAttachmentInvLinkEnabled; bool mOutfitIsDirty; bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls. + bool mOutstandingAppearanceBakeRequest; // A bake request is outstanding. Do not overlap. + bool mRerequestAppearanceBake; /** * Lock for blocking operations on outfit until server reply or timeout exceed -- cgit v1.2.3