diff options
author | Oz Linden <oz@lindenlab.com> | 2016-04-04 15:53:09 -0400 |
---|---|---|
committer | Oz Linden <oz@lindenlab.com> | 2016-04-04 15:53:09 -0400 |
commit | 9be58e915a6c69de280ccabd3019e9ac40beed26 (patch) | |
tree | ad6f8f1f754a865afb761d0f17744cc7e1ef8b74 /indra/newview/llavatarrenderinfoaccountant.cpp | |
parent | ab46c9226bd9048fa218f54bc8668594401529e7 (diff) | |
parent | 18928ea6c6f2830a0d45ec412c915eceff1b76b0 (diff) |
merge with 4.0.3-release
Diffstat (limited to 'indra/newview/llavatarrenderinfoaccountant.cpp')
-rw-r--r-- | indra/newview/llavatarrenderinfoaccountant.cpp | 533 |
1 files changed, 244 insertions, 289 deletions
diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index 2760a97bda..2be3e8546f 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -28,17 +28,14 @@ // Precompiled header #include "llviewerprecompiledheaders.h" +// associated header +#include "llavatarrenderinfoaccountant.h" +#include "llavatarrendernotifier.h" // STL headers // std headers // external library headers // other Linden headers #include "llcharacter.h" -#include "httprequest.h" -#include "httphandler.h" -#include "httpresponse.h" -#include "llcorehttputil.h" -#include "llappcorehttp.h" -#include "llavatarrendernotifier.h" #include "lltimer.h" #include "llviewercontrol.h" #include "llviewermenu.h" @@ -46,9 +43,10 @@ #include "llviewerregion.h" #include "llvoavatar.h" #include "llworld.h" -// associated header -#include "llavatarrenderinfoaccountant.h" - +#include "llhttpsdhandler.h" +#include "httpheaders.h" +#include "httpoptions.h" +#include "llcorehttputil.h" static const std::string KEY_AGENTS = "agents"; // map static const std::string KEY_WEIGHT = "weight"; // integer @@ -60,329 +58,286 @@ static const std::string KEY_IDENTIFIER = "identifier"; static const std::string KEY_MESSAGE = "message"; static const std::string KEY_ERROR = "error"; - static const F32 SECS_BETWEEN_REGION_SCANS = 5.f; // Scan the region list every 5 seconds static const F32 SECS_BETWEEN_REGION_REQUEST = 15.0; // Look for new avs every 15 seconds static const F32 SECS_BETWEEN_REGION_REPORTS = 60.0; // Update each region every 60 seconds -// The policy class for HTTP traffic; this is the right value for all capability requests. -static LLCore::HttpRequest::policy_t http_policy(LLAppCoreHttp::AP_REPORTING); - -// Priority for HTTP requests. Use 0U. -static LLCore::HttpRequest::priority_t http_priority(0U); - +//========================================================================= LLAvatarRenderInfoAccountant::LLAvatarRenderInfoAccountant() - : mHttpRequest(new LLCore::HttpRequest) - , mHttpHeaders(new LLCore::HttpHeaders) - , mHttpOptions(new LLCore::HttpOptions) { - mHttpOptions->setTransferTimeout(SECS_BETWEEN_REGION_SCANS); - - mHttpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_LLSD_XML); - mHttpHeaders->append(HTTP_OUT_HEADER_ACCEPT, HTTP_CONTENT_LLSD_XML); } LLAvatarRenderInfoAccountant::~LLAvatarRenderInfoAccountant() { - mHttpOptions->release(); - mHttpHeaders->release(); - // delete mHttpRequest; ??? } -// HTTP responder class for GET request for avatar render weight information -class LLAvatarRenderInfoGetHandler : public LLCore::HttpHandler + +void LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro(std::string url, U64 regionHandle) { -private: - LOG_CLASS(LLAvatarRenderInfoGetHandler); - -public: - LLAvatarRenderInfoGetHandler() : LLCore::HttpHandler() - { - } + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + if (!regionp) + { + LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight info received but region not found for " + << regionHandle << LL_ENDL; + return; + } + + regionp->getRenderInfoRequestTimer().resetWithExpiry(SECS_BETWEEN_REGION_REQUEST); + + LLSD httpResults = result["http_result"]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + LL_WARNS("AvatarRenderInfoAccountant") << "HTTP status, " << status.toTerseString() << LL_ENDL; + return; + } + + if (result.has(KEY_AGENTS)) + { + const LLSD & avatar_render_info = result[KEY_AGENTS]; + if (avatar_render_info.isMap()) + { + if ( avatar_render_info.has(KEY_REPORTING_COMPLEXITY_LIMIT) + && avatar_render_info.has(KEY_OVER_COMPLEXITY_LIMIT)) + { + U32 reporting = avatar_render_info[KEY_REPORTING_COMPLEXITY_LIMIT].asInteger(); + U32 overlimit = avatar_render_info[KEY_OVER_COMPLEXITY_LIMIT].asInteger(); - void onCompleted(LLCore::HttpHandle handle, - LLCore::HttpResponse* response) - { - LLCore::HttpStatus status = response->getStatus(); - if (status) + LL_DEBUGS("AvatarRenderInfo") << "complexity limit: "<<reporting<<" reporting, "<<overlimit<<" over limit"<<LL_ENDL; + + LLAvatarRenderNotifier::getInstance()->updateNotificationRegion(reporting, overlimit); + } + + if (avatar_render_info.has(KEY_AGENTS)) { - LL_DEBUGS("AvatarRenderInfo") << "response"<<LL_ENDL; - LLSD avatar_render_info; - if (LLCoreHttpUtil::responseToLLSD(response, false /* quiet logging */, - avatar_render_info)) - { - if (avatar_render_info.isMap()) - { - if ( avatar_render_info.has(KEY_REPORTING_COMPLEXITY_LIMIT) - && avatar_render_info.has(KEY_OVER_COMPLEXITY_LIMIT)) - { - U32 reporting = avatar_render_info[KEY_REPORTING_COMPLEXITY_LIMIT].asInteger(); - U32 overlimit = avatar_render_info[KEY_OVER_COMPLEXITY_LIMIT].asInteger(); - - LL_DEBUGS("AvatarRenderInfo") << "complexity limit: "<<reporting<<" reporting, "<<overlimit<<" over limit"<<LL_ENDL; - - LLAvatarRenderNotifier::getInstance()->updateNotificationRegion(reporting, overlimit); + const LLSD & agents = avatar_render_info[KEY_AGENTS]; + if (agents.isMap()) + { + for (LLSD::map_const_iterator agent_iter = agents.beginMap(); + agent_iter != agents.endMap(); + agent_iter++ + ) + { + LLUUID target_agent_id = LLUUID(agent_iter->first); + LLViewerObject* avatarp = gObjectList.findObject(target_agent_id); + if (avatarp && avatarp->isAvatar()) + { + const LLSD & agent_info_map = agent_iter->second; + if (agent_info_map.isMap()) + { + LL_DEBUGS("AvatarRenderInfo") << " Agent " << target_agent_id + << ": " << agent_info_map << LL_ENDL; + + if (agent_info_map.has(KEY_WEIGHT)) + { + ((LLVOAvatar *) avatarp)->setReportedVisualComplexity(agent_info_map[KEY_WEIGHT].asInteger()); + } + } + else + { + LL_WARNS("AvatarRenderInfo") << "agent entry invalid" + << " agent " << target_agent_id + << " map " << agent_info_map + << LL_ENDL; + } } - - if (avatar_render_info.has(KEY_AGENTS)) - { - const LLSD & agents = avatar_render_info[KEY_AGENTS]; - if (agents.isMap()) - { - for (LLSD::map_const_iterator agent_iter = agents.beginMap(); - agent_iter != agents.endMap(); - agent_iter++ - ) - { - LLUUID target_agent_id = LLUUID(agent_iter->first); - LLViewerObject* avatarp = gObjectList.findObject(target_agent_id); - if (avatarp && avatarp->isAvatar()) - { - const LLSD & agent_info_map = agent_iter->second; - if (agent_info_map.isMap()) - { - LL_DEBUGS("AvatarRenderInfo") << " Agent " << target_agent_id - << ": " << agent_info_map << LL_ENDL; - - if (agent_info_map.has(KEY_WEIGHT)) - { - ((LLVOAvatar *) avatarp)->setReportedVisualComplexity(agent_info_map[KEY_WEIGHT].asInteger()); - } - } - else - { - LL_WARNS("AvatarRenderInfo") << "agent entry invalid" - << " agent " << target_agent_id - << " map " << agent_info_map - << LL_ENDL; - } - } - else - { - LL_DEBUGS("AvatarRenderInfo") << "Unknown agent " << target_agent_id << LL_ENDL; - } - } // for agent_iter - } - else - { - LL_WARNS("AvatarRenderInfo") << "malformed get response agents avatar_render_info is not map" << LL_ENDL; - } - } // has "agents" - else if (avatar_render_info.has(KEY_ERROR)) - { - const LLSD & error = avatar_render_info[KEY_ERROR]; - LL_WARNS("AvatarRenderInfo") << "Avatar render info GET error: " - << error[KEY_IDENTIFIER] - << ": " << error[KEY_MESSAGE] - << LL_ENDL; - } - else - { - LL_WARNS("AvatarRenderInfo") << "no agent key in get response" << LL_ENDL; - } - } - else - { - LL_WARNS("AvatarRenderInfo") << "malformed get response is not map" << LL_ENDL; - } + else + { + LL_DEBUGS("AvatarRenderInfo") << "Unknown agent " << target_agent_id << LL_ENDL; + } + } // for agent_iter } - else - { - LL_WARNS("AvatarRenderInfo") << "malformed get response parse failure" << LL_ENDL; - } + else + { + LL_WARNS("AvatarRenderInfo") << "malformed get response agents avatar_render_info is not map" << LL_ENDL; + } + } // has "agents" + else if (avatar_render_info.has(KEY_ERROR)) + { + const LLSD & error = avatar_render_info[KEY_ERROR]; + LL_WARNS("AvatarRenderInfo") << "Avatar render info GET error: " + << error[KEY_IDENTIFIER] + << ": " << error[KEY_MESSAGE] + << LL_ENDL; } else { - // Something went wrong. Translate the status to - // a meaningful message. - LL_WARNS("AvatarRenderInfo") << "GET failed Status: " - << status.toTerseString() - << ", Reason: " << status.toString() - << LL_ENDL; - } - - delete this; // release the handler object - } -}; + LL_WARNS("AvatarRenderInfo") << "no agent key in get response" << LL_ENDL; + } + } + else + { + LL_WARNS("AvatarRenderInfo") << "malformed get response is not map" << LL_ENDL; + } + } // has "agents" + else if (result.has(KEY_ERROR)) + { + const LLSD & error = result[KEY_ERROR]; + LL_WARNS() << "Avatar render info GET error: " + << error[KEY_IDENTIFIER] + << ": " << error[KEY_MESSAGE] + << " from region " << regionp->getName() + << LL_ENDL; + } +} -// HTTP responder class for POST request for avatar render weight information -class LLAvatarRenderInfoPostHandler : public LLCore::HttpHandler +//------------------------------------------------------------------------- +void LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro(std::string url, U64 regionHandle) { - private: - LOG_CLASS(LLAvatarRenderInfoPostHandler); - - public: - LLAvatarRenderInfoPostHandler() : LLCore::HttpHandler() - { - } - - void onCompleted(LLCore::HttpHandle handle, - LLCore::HttpResponse* response) - { - LLCore::HttpStatus status = response->getStatus(); - if (status) - { - LL_DEBUGS("AvatarRenderInfo") << "post succeeded" << LL_ENDL; - } - else - { - // Something went wrong. Translate the status to - // a meaningful message. - LL_WARNS("AvatarRenderInfo") << "POST failed Status: " - << status.toTerseString() - << ", Reason: " << status.toString() - << LL_ENDL; - } - - delete this; // release the handler object - } -}; - + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("AvatarRenderInfoAccountant", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + if (!regionp) + { + LL_WARNS("AvatarRenderInfoAccountant") << "Avatar render weight calculation but region not found for " + << regionHandle << LL_ENDL; + return; + } + + LL_DEBUGS("AvatarRenderInfoAccountant") + << "Sending avatar render info for region " << regionp->getName() + << " to " << url << LL_ENDL; + + U32 num_avs = 0; + // Build the render info to POST to the region + LLSD agents = LLSD::emptyMap(); + + std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + while( iter != LLCharacter::sInstances.end() ) + { + LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*iter); + if (avatar && + avatar->getRezzedStatus() >= 2 && // Mostly rezzed (maybe without baked textures downloaded) + !avatar->isDead() && // Not dead yet + avatar->getObjectHost() == regionp->getHost()) // Ensure it's on the same region + { + avatar->calculateUpdateRenderComplexity(); // Make sure the numbers are up-to-date + + LLSD info = LLSD::emptyMap(); + U32 avatar_complexity = avatar->getVisualComplexity(); + if (avatar_complexity > 0) + { + // the weight/complexity is unsigned, but LLSD only stores signed integers, + // so if it's over that (which would be ridiculously high), just store the maximum signed int value + info[KEY_WEIGHT] = (S32)(avatar_complexity < S32_MAX ? avatar_complexity : S32_MAX); + info[KEY_TOO_COMPLEX] = LLSD::Boolean(avatar->isTooComplex()); + agents[avatar->getID().asString()] = info; + + LL_DEBUGS("AvatarRenderInfo") << "Sending avatar render info for " << avatar->getID() + << ": " << info << LL_ENDL; + num_avs++; + } + } + iter++; + } + + // Reset this regions timer, moving to longer intervals if there are lots of avatars around + regionp->getRenderInfoReportTimer().resetWithExpiry(SECS_BETWEEN_REGION_REPORTS + (2.f * num_avs)); + + if (num_avs == 0) + return; // nothing to report + + LLSD report = LLSD::emptyMap(); + report[KEY_AGENTS] = agents; + + regionp = NULL; + LLSD result = httpAdapter->postAndSuspend(httpRequest, url, report); + + regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle); + if (!regionp) + { + LL_INFOS("AvatarRenderInfoAccountant") << "Avatar render weight POST result received but region not found for " + << regionHandle << LL_ENDL; + return; + } + + LLSD httpResults = result["http_result"]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + if (!status) + { + LL_WARNS("AvatarRenderInfoAccountant") << "HTTP status, " << status.toTerseString() << LL_ENDL; + return; + } + + if (result.isMap()) + { + if (result.has(KEY_ERROR)) + { + const LLSD & error = result[KEY_ERROR]; + LL_WARNS("AvatarRenderInfoAccountant") << "POST error: " + << error[KEY_IDENTIFIER] + << ": " << error[KEY_MESSAGE] + << " from region " << regionp->getName() + << LL_ENDL; + } + else + { + LL_DEBUGS("AvatarRenderInfoAccountant") + << "POST result for region " << regionp->getName() + << ": " << result + << LL_ENDL; + } + } + else + { + LL_WARNS("AvatarRenderInfoAccountant") << "Malformed POST response from region '" << regionp->getName() + << LL_ENDL; + } +} // Send request for avatar weights in one region // called when the mRenderInfoScanTimer expires (forced when entering a new region) void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regionp) { - if ( regionp->getRenderInfoReportTimer().hasExpired() ) // Time to make request + std::string url = regionp->getCapability("AvatarRenderInfo"); + if ( !url.empty() // we have the capability + && regionp->getRenderInfoReportTimer().hasExpired() // Time to make request) + ) { - U32 num_avs = 0; - - std::string url = regionp->getCapability("AvatarRenderInfo"); - if (!url.empty()) - { - // Build the render info to POST to the region - LLSD agents = LLSD::emptyMap(); - - std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); - while( iter != LLCharacter::sInstances.end() ) - { - LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*iter); - if (avatar && - avatar->getRezzedStatus() >= 2 && // Mostly rezzed (maybe without baked textures downloaded) - !avatar->isDead() && // Not dead yet - avatar->getObjectHost() == regionp->getHost()) // Ensure it's on the same region - { - avatar->calculateUpdateRenderComplexity(); // Make sure the numbers are up-to-date - - LLSD info = LLSD::emptyMap(); - U32 avatar_complexity = avatar->getVisualComplexity(); - if (avatar_complexity > 0) - { - // the weight/complexity is unsigned, but LLSD only stores signed integers, - // so if it's over that (which would be ridiculously high), just store the maximum signed int value - info[KEY_WEIGHT] = (S32)(avatar_complexity < S32_MAX ? avatar_complexity : S32_MAX); - info[KEY_TOO_COMPLEX] = LLSD::Boolean(avatar->isTooComplex()); - agents[avatar->getID().asString()] = info; - - LL_DEBUGS("AvatarRenderInfo") << "Sending avatar render info for " << avatar->getID() - << ": " << info << LL_ENDL; - num_avs++; - } - } - iter++; - } - - if (num_avs > 0) - { - LLSD report = LLSD::emptyMap(); - report[KEY_AGENTS] = agents; - - LLCore::HttpHandle handle(LLCORE_HTTP_HANDLE_INVALID); - LLAvatarRenderInfoPostHandler* handler = new LLAvatarRenderInfoPostHandler; - - handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, - http_policy, - http_priority, - url, - report, - mHttpOptions, - mHttpHeaders, - handler); - if (LLCORE_HTTP_HANDLE_INVALID == handle) - { - LLCore::HttpStatus status(mHttpRequest->getStatus()); - LL_WARNS("AvatarRenderInfo") << "HTTP POST request failed" - << " Status: " << status.toTerseString() - << " Reason: '" << status.toString() << "'" - << LL_ENDL; - delete handler; - } - else - { - LL_DEBUGS("AvatarRenderInfo") << "Sent render costs for " << num_avs - << " avatars to region " << regionp->getName() - << LL_ENDL; - - - } - } - else - { - LL_DEBUGS("AvatarRenderInfo") << "no agent info to send" << LL_ENDL; - } - } - else - { - LL_WARNS("AvatarRenderInfo") << "AvatarRenderInfo cap is empty" << LL_ENDL; - } - - // Reset this regions timer, moving to longer intervals if there are lots of avatars around - regionp->getRenderInfoReportTimer().resetWithExpiry(SECS_BETWEEN_REGION_REPORTS + (2.f * num_avs)); + std::string coroname = + LLCoros::instance().launch("LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro", + boost::bind(&LLAvatarRenderInfoAccountant::avatarRenderInfoReportCoro, url, regionp->getHandle())); } } - - - -// static -// Send request for one region, no timer checks +// Send request for avatar weights in one region +// called when the mRenderInfoScanTimer expires (forced when entering a new region) void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regionp) { - if (regionp->getRenderInfoRequestTimer().hasExpired()) + std::string url = regionp->getCapability("AvatarRenderInfo"); + if ( !url.empty() + && regionp->getRenderInfoRequestTimer().hasExpired() + ) { - std::string url = regionp->getCapability("AvatarRenderInfo"); - if (!url.empty()) - { - - LLAvatarRenderInfoGetHandler* handler = new LLAvatarRenderInfoGetHandler; - // First send a request to get the latest data - LLCore::HttpHandle handle = mHttpRequest->requestGet(http_policy, - http_priority, - url, - NULL, - NULL, - handler); - if (LLCORE_HTTP_HANDLE_INVALID != handle) - { - LL_DEBUGS("AvatarRenderInfo") << "Requested avatar render info for region " - << regionp->getName() - << LL_ENDL; - } - else - { - LL_WARNS("AvatarRenderInfo") << "Failed to launch HTTP GET request. Try again." - << LL_ENDL; - delete handler; - } - } - else - { - LL_WARNS("AvatarRenderInfo") << "no AvatarRenderInfo cap for " << regionp->getName() << LL_ENDL; - } - - regionp->getRenderInfoRequestTimer().resetWithExpiry(SECS_BETWEEN_REGION_REQUEST); + LL_DEBUGS("AvatarRenderInfo") + << "Requesting avatar render info for region " << regionp->getName() + << " from " << url + << LL_ENDL; + + // First send a request to get the latest data + std::string coroname = + LLCoros::instance().launch("LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro", + boost::bind(&LLAvatarRenderInfoAccountant::avatarRenderInfoGetCoro, url, regionp->getHandle())); } } - // static // Called every frame - send render weight requests to every region void LLAvatarRenderInfoAccountant::idle() { - mHttpRequest->update(0); // give any pending http operations a chance to call completion methods - if (mRenderInfoScanTimer.hasExpired()) { LL_DEBUGS("AvatarRenderInfo") << "Scanning regions for render info updates" |