diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index e1cf91e089..eea4532d02 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3741,154 +3741,140 @@ LLSD LLAppearanceMgr::dumpCOF() const void LLAppearanceMgr::requestServerAppearanceUpdate() { - if (!mIsServerBakeOutstanding) - { - LLCoros::instance().launch("LLAppearanceMgr::serverAppearanceUpdateCoro", - boost::bind(&LLAppearanceMgr::serverAppearanceUpdateCoro, this)); - } - else - { - LL_WARNS("Avatar") << "Server bake request would overlap outstanding request " << - " requesting new bake when ready." << LL_ENDL; - mNewServerBakeRequested = true; - } + LLCoprocedureManager::CoProcedure_t proc = boost::bind(&LLAppearanceMgr::serverAppearanceUpdateCoro, this, _1); + LLCoprocedureManager::instance().enqueueCoprocedure("AIS", "LLAppearanceMgr::serverAppearanceUpdateCoro", proc); } -void LLAppearanceMgr::serverAppearanceUpdateCoro() +void LLAppearanceMgr::serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter) { - BoolSetter inFlight(mIsServerBakeOutstanding); - - do + if (!gAgent.getRegion()) { + LL_WARNS("Avatar") << "Region not set, cannot request server appearance update" << LL_ENDL; + return; + } + if (gAgent.getRegion()->getCentralBakeVersion() == 0) + { + LL_WARNS("Avatar") << "Region does not support baking" << LL_ENDL; + return; + } + + std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance"); + if (url.empty()) + { + LL_WARNS("Agent") << "Could not retrieve region capability \"UpdateAvatarAppearance\"" << LL_ENDL; + return; + } + + //---------------- + if (gAgentAvatarp->isEditingAppearance()) + { + LL_WARNS("Avatar") << "Avatar editing appearance, not sending request." << LL_ENDL; + // don't send out appearance updates if in appearance editing mode + return; + } + #if 0 - static int reqcount = 0; - int r_count = ++reqcount; - LL_WARNS("Avatar") << "START: Server Bake request #" << r_count << "!" << LL_ENDL; + 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, ignore. - S32 cofVersion = getCOFVersion(); - S32 lastRcv = gAgentAvatarp->mLastUpdateReceivedCOFVersion; - S32 lastReq = gAgentAvatarp->mLastUpdateRequestCOFVersion; + // 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; - mNewServerBakeRequested = false; - //---------------- - // move out of coroutine - if (!gAgent.getRegion()) - { - LL_WARNS("Avatar") << "Region not set, cannot request server appearance update" << LL_ENDL; - return; - } - if (gAgent.getRegion()->getCentralBakeVersion() == 0) - { - LL_WARNS("Avatar") << "Region does not support baking" << LL_ENDL; - } - - std::string url = gAgent.getRegion()->getCapability("UpdateAvatarAppearance"); - if (url.empty()) - { - LL_WARNS("Agent") << "Could not retrieve region capability \"UpdateAvatarAppearance\"" << LL_ENDL; - } - - //---------------- - if (gAgentAvatarp->isEditingAppearance()) - { - LL_WARNS("Avatar") << "Avatar editing appearance, not sending request." << LL_ENDL; - // don't send out appearance updates if in appearance editing mode - return; - } - - LL_DEBUGS("Avatar") << "COF version=" << cofVersion << - " last_rcv=" << lastRcv << - " last_req=" << lastReq << LL_ENDL; + LL_INFOS("Avatar") << "Requesting COF version " << cofVersion << + " (Last Received:" << lastRcv << ")" << + " (Last Requested:" << lastReq << ")" << LL_ENDL; + if ((cofVersion != LLViewerInventoryCategory::VERSION_UNKNOWN)) + { if (cofVersion < lastRcv) { LL_WARNS("Avatar") << "Have already received update for cof version " << lastRcv - << " will not request for " << cofVersion << LL_ENDL; - return; + << " but requesting for " << cofVersion << LL_ENDL; } - if (lastReq >= cofVersion) + if (lastReq > cofVersion) { LL_WARNS("Avatar") << "Request already in flight for cof version " << lastReq - << " will not request for " << cofVersion << LL_ENDL; - return; + << " but requesting for " << cofVersion << LL_ENDL; } + } - // Actually send the request. - LL_DEBUGS("Avatar") << "Will send request for cof_version " << cofVersion << LL_ENDL; + // 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())); +// LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter( +// "UpdateAvatarAppearance", gAgent.getAgentPolicy())); - S32 reqCofVersion = cofVersion; + 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; LL_WARNS("Avatar") << "Forcing version failure on COF Baking" << LL_ENDL; } - do + LL_INFOS() << "Requesting bake for COF version " << reqCofVersion << LL_ENDL; + + LLSD postData; + if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate")) { - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); + postData = dumpCOF(); + } + else + { + postData["cof_version"] = reqCofVersion; + } - LLSD postData; - if (gSavedSettings.getBOOL("DebugAvatarExperimentalServerAppearanceUpdate")) + gAgentAvatarp->mLastUpdateRequestCOFVersion = reqCofVersion; + + LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status || !result["success"].asBoolean()) + { + std::string message = (result.has("error")) ? result["error"].asString() : status.toString(); + LL_WARNS("Avatar") << "Appearance Failure. server responded with \"" << message << "\"" << LL_ENDL; + + // We may have requested a bake for a stale COF (especially if the inventory + // is still updating. If that is the case re send the request with the + // corrected COF version. (This may also be the case if the viewer is running + // on multiple machines. + if (result.has("expected")) { - postData = dumpCOF(); - } - else - { - postData["cof_version"] = reqCofVersion; + S32 expectedCofVersion = result["expected"].asInteger(); + bRetry = true; + // Wait for a 1/2 second before trying again. Just to keep from asking too quickly. + llcoro::suspendUntilTimeout(0.5); + + LL_WARNS("Avatar") << "Server expected " << expectedCofVersion << " as COF version" << LL_ENDL; + continue; } + } - gAgentAvatarp->mLastUpdateRequestCOFVersion = reqCofVersion; + LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL; + if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) + { + dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", result); + } - LLSD result = httpAdapter->postAndSuspend(httpRequest, url, postData); - - LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); - - if (!status || !result["success"].asBoolean()) - { - std::string message = (result.has("error")) ? result["error"].asString() : status.toString(); - LL_WARNS("Avatar") << "Appearance Failure. server responded with \"" << message << "\"" << LL_ENDL; - - // We may have requested a bake for a stale COF (especially if the inventory - // is still updating. If that is the case re send the request with the - // corrected COF version. (This may also be the case if the viewer is running - // on multiple machines. - if (result.has("expected")) - { - reqCofVersion = result["expected"].asInteger(); - - LL_WARNS("Avatar") << "Will Retry with expected COF value of " << reqCofVersion << LL_ENDL; - continue; - } - - break; - } - - LL_DEBUGS("Avatar") << "succeeded" << LL_ENDL; - if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) - { - dump_sequential_xml(gAgentAvatarp->getFullname() + "_appearance_request_ok", result); - } - - break; - } while (true); + } while (bRetry); #if 0 - LL_WARNS("Avatar") << "END: Server Bake request #" << r_count << "!" << LL_ENDL; + LL_WARNS("Avatar") << "END: Server Bake request #" << r_count << "!" << LL_ENDL; #endif - // if someone requested a server bake before the previous one was finished - // repeate the process. - if (mNewServerBakeRequested) - { - LL_WARNS("Avatar") << "New bake request received while processing previous one. Re-requesting." << LL_ENDL; - } - } while (mNewServerBakeRequested); } /*static*/ @@ -4305,9 +4291,7 @@ LLAppearanceMgr::LLAppearanceMgr(): mOutfitLocked(false), mInFlightCounter(0), mInFlightTimer(), - mIsInUpdateAppearanceFromCOF(false), - mIsServerBakeOutstanding(false), - mNewServerBakeRequested(false) + mIsInUpdateAppearanceFromCOF(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 9dee9ffbbd..efe141951d 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -34,6 +34,7 @@ #include "llinventorymodel.h" #include "llinventoryobserver.h" #include "llviewerinventory.h" +#include "llcorehttputil.h" class LLWearableHoldingPattern; class LLInventoryCallback; @@ -245,7 +246,7 @@ public: private: - void serverAppearanceUpdateCoro(); + void serverAppearanceUpdateCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter); static void debugAppearanceUpdateCOF(const LLSD& content); std::string mAppearanceServiceURL; @@ -272,8 +273,6 @@ private: bool mAttachmentInvLinkEnabled; bool mOutfitIsDirty; bool mIsInUpdateAppearanceFromCOF; // to detect recursive calls. - bool mIsServerBakeOutstanding; // A server texture bake has been sent to the server and we are waiting on a response. - bool mNewServerBakeRequested; // A server texture bake has been requested, but there is already one outstanding. /** * Lock for blocking operations on outfit until server reply or timeout exceed diff --git a/indra/newview/llpathfindingcharacterlist.cpp b/indra/newview/llpathfindingcharacterlist.cpp index 12340cebfa..d63daaa59b 100755 --- a/indra/newview/llpathfindingcharacterlist.cpp +++ b/indra/newview/llpathfindingcharacterlist.cpp @@ -40,14 +40,14 @@ //--------------------------------------------------------------------------- LLPathfindingCharacterList::LLPathfindingCharacterList() - : LLPathfindingObjectList() + : LLPathfindingObjectList() { } LLPathfindingCharacterList::LLPathfindingCharacterList(const LLSD& pCharacterListData) - : LLPathfindingObjectList() + : LLPathfindingObjectList() { - parseCharacterListData(pCharacterListData); + parseCharacterListData(pCharacterListData); } LLPathfindingCharacterList::~LLPathfindingCharacterList() @@ -56,14 +56,16 @@ LLPathfindingCharacterList::~LLPathfindingCharacterList() void LLPathfindingCharacterList::parseCharacterListData(const LLSD& pCharacterListData) { - LLPathfindingObjectMap &objectMap = getObjectMap(); + LLPathfindingObjectMap &objectMap = getObjectMap(); - for (LLSD::map_const_iterator characterDataIter = pCharacterListData.beginMap(); - characterDataIter != pCharacterListData.endMap(); ++characterDataIter) - { - const std::string& uuid(characterDataIter->first); - const LLSD& characterData = characterDataIter->second; - LLPathfindingObjectPtr character(new LLPathfindingCharacter(uuid, characterData)); - objectMap.insert(std::pair(uuid, character)); - } + for (LLSD::map_const_iterator characterDataIter = pCharacterListData.beginMap(); + characterDataIter != pCharacterListData.endMap(); ++characterDataIter) + { + if (characterDataIter->second.isUndefined()) + continue; + const std::string& uuid(characterDataIter->first); + const LLSD& characterData = characterDataIter->second; + LLPathfindingObjectPtr character(new LLPathfindingCharacter(uuid, characterData)); + objectMap.insert(std::pair(uuid, character)); + } } diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index f7ef06f765..f0281ad7b2 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -8093,6 +8093,7 @@ bool resolve_appearance_version(const LLAppearanceMessageContents& contents, S32 //----------------------------------------------------------------------------- void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { + static S32 largestSelfCOFSeen(LLViewerInventoryCategory::VERSION_UNKNOWN); LL_DEBUGS("Avatar") << "starts" << LL_ENDL; // Use LLCachedControl @@ -8139,6 +8140,14 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) << " last_update_request_cof_version " << last_update_request_cof_version << " my_cof_version " << LLAppearanceMgr::instance().getCOFVersion() << LL_ENDL; + if (largestSelfCOFSeen > this_update_cof_version) + { + LL_WARNS("Avatar") << "Already processed appearance for COF version " << + largestSelfCOFSeen << ", discarding appearance with COF " << this_update_cof_version << LL_ENDL; + return; + } + largestSelfCOFSeen = this_update_cof_version; + // [Legacy Bake] if (getRegion() && (getRegion()->getCentralBakeVersion()==0)) { @@ -8186,6 +8195,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) } // No backsies zone - if we get here, the message should be valid and usable, will be processed. + LL_INFOS("Avatar") << "Processing appearance message version " << this_update_cof_version << LL_ENDL; // [Legacy Bake] if (appearance_version > 0)