summaryrefslogtreecommitdiff
path: root/indra/newview/llavatarrenderinfoaccountant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llavatarrenderinfoaccountant.cpp')
-rw-r--r--indra/newview/llavatarrenderinfoaccountant.cpp470
1 files changed, 266 insertions, 204 deletions
diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp
index 83ae0438d9..8631f245a9 100644
--- a/indra/newview/llavatarrenderinfoaccountant.cpp
+++ b/indra/newview/llavatarrenderinfoaccountant.cpp
@@ -28,14 +28,16 @@
// Precompiled header
#include "llviewerprecompiledheaders.h"
-// associated header
-#include "llavatarrenderinfoaccountant.h"
// STL headers
// std headers
// external library headers
// other Linden headers
#include "llcharacter.h"
-#include "llhttpclient.h"
+#include "httprequest.h"
+#include "httphandler.h"
+#include "httpresponse.h"
+#include "llcorehttputil.h"
+#include "llappcorehttp.h"
#include "lltimer.h"
#include "llviewercontrol.h"
#include "llviewermenu.h"
@@ -43,6 +45,8 @@
#include "llviewerregion.h"
#include "llvoavatar.h"
#include "llworld.h"
+// associated header
+#include "llavatarrenderinfoaccountant.h"
static const std::string KEY_AGENTS = "agents"; // map
@@ -53,228 +57,259 @@ static const std::string KEY_MESSAGE = "message";
static const std::string KEY_ERROR = "error";
-// Send data updates about once per minute, only need per-frame resolution
-LLFrameTimer LLAvatarRenderInfoAccountant::sRenderInfoReportTimer;
+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 LLAvatarRenderInfoGetResponder : public LLHTTPClient::Responder
+class LLAvatarRenderInfoGetHandler : public LLCore::HttpHandler
{
+private:
+ LOG_CLASS(LLAvatarRenderInfoGetHandler);
+
public:
- LLAvatarRenderInfoGetResponder(U64 region_handle) : mRegionHandle(region_handle)
+ LLAvatarRenderInfoGetHandler() : LLCore::HttpHandler()
{
}
- virtual void error(U32 statusNum, const std::string& reason)
- {
- LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
- if (regionp)
+ void onCompleted(LLCore::HttpHandle handle,
+ LLCore::HttpResponse* response)
{
- LL_WARNS("AvatarRenderInfo") << "HTTP error result for avatar weight GET: " << statusNum
- << ", " << reason
- << " returned by region " << regionp->getName()
- << LL_ENDL;
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "Avatar render weight GET error recieved but region not found for "
- << mRegionHandle
- << ", error " << statusNum
- << ", " << reason
- << LL_ENDL;
- }
-
- }
-
- virtual void result(const LLSD& content)
- {
- LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
- if (regionp)
- {
- LL_DEBUGS("AvatarRenderInfo") << "LRI: Result for avatar weights request for region '" << regionp->getName() << "':" << LL_ENDL;
-
- if (content.isMap())
- {
- if (content.has(KEY_AGENTS))
+ LLCore::HttpStatus status = response->getStatus();
+ if (status)
+ {
+ LLSD avatar_render_info;
+ if (LLCoreHttpUtil::responseToLLSD(response, false /* quiet logging */,
+ avatar_render_info))
{
- const LLSD & agents = content[KEY_AGENTS];
- if (agents.isMap())
+ if (avatar_render_info.isMap())
{
- LLSD::map_const_iterator report_iter = agents.beginMap();
- while (report_iter != agents.endMap())
+ if (avatar_render_info.has(KEY_AGENTS))
{
- LLUUID target_agent_id = LLUUID(report_iter->first);
- const LLSD & agent_info_map = report_iter->second;
- LLViewerObject* avatarp = gObjectList.findObject(target_agent_id);
- if ( avatarp
- && avatarp->isAvatar()
- && agent_info_map.isMap())
- { // Extract the data for this avatar
-
- LL_DEBUGS("AvatarRenderInfo") << "LRI: Agent " << target_agent_id
- << ": " << agent_info_map << LL_ENDL;
-
- if (agent_info_map.has(KEY_WEIGHT))
+ 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++
+ )
{
- ((LLVOAvatar *) avatarp)->setReportedVisualComplexity(agent_info_map[KEY_WEIGHT].asInteger());
- }
+ 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") << "LRI: agent entry invalid"
- << " agent " << target_agent_id
- << " map " << agent_info_map
- << LL_ENDL;
+ LL_WARNS("AvatarRenderInfo") << "malformed get response agents avatar_render_info is not map" << LL_ENDL;
}
- report_iter++;
+ } // 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") << "LRI: malformed get response agents content is not map" << LL_ENDL;
+ LL_WARNS("AvatarRenderInfo") << "malformed get response is not map" << LL_ENDL;
}
-
- } // has "agents"
- else if (content.has(KEY_ERROR))
- {
- const LLSD & error = content[KEY_ERROR];
- LL_WARNS("AvatarRenderInfo") << "Avatar render info GET error: "
- << error[KEY_IDENTIFIER]
- << ": " << error[KEY_MESSAGE]
- << " from region " << regionp->getName()
- << LL_ENDL;
- }
+ }
else
{
- LL_WARNS("AvatarRenderInfo") << "LRI: no agent key in get response" << LL_ENDL;
+ LL_WARNS("AvatarRenderInfo") << "malformed get response parse failure" << LL_ENDL;
}
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "LRI: malformed get response is not map" << LL_ENDL;
- }
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "Avatar render weight info recieved but region not found for "
- << mRegionHandle << 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
}
- }
-
-private:
- U64 mRegionHandle;
};
// HTTP responder class for POST request for avatar render weight information
-class LLAvatarRenderInfoPostResponder : public LLHTTPClient::Responder
+class LLAvatarRenderInfoPostHandler : public LLCore::HttpHandler
{
-public:
- LLAvatarRenderInfoPostResponder(U64 region_handle) : mRegionHandle(region_handle)
- {
- }
+ private:
+ LOG_CLASS(LLAvatarRenderInfoPostHandler);
- virtual void error(U32 statusNum, const std::string& reason)
+ public:
+ LLAvatarRenderInfoPostHandler() : LLCore::HttpHandler()
{
- LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
- if (regionp)
- {
- LL_WARNS("AvatarRenderInfo") << "HTTP error result for avatar weight POST: " << statusNum
- << ", " << reason
- << " returned by region " << regionp->getName()
- << LL_ENDL;
- }
- else
- {
- LL_WARNS("AvatarRenderInfo") << "Avatar render weight POST error recieved but region not found for "
- << mRegionHandle
- << ", error " << statusNum
- << ", " << reason
- << LL_ENDL;
- }
}
- virtual void result(const LLSD& content)
- {
- LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle);
- if (regionp)
+ void onCompleted(LLCore::HttpHandle handle,
+ LLCore::HttpResponse* response)
{
- LL_DEBUGS("AvatarRenderInfo") << "LRI: Result for avatar weights POST for region " << regionp->getName()
- << ": " << content << LL_ENDL;
-
- if (content.isMap())
+ LLCore::HttpStatus status = response->getStatus();
+ if (status)
{
- if (content.has(KEY_ERROR))
- {
- const LLSD & error = content[KEY_ERROR];
- LL_WARNS("AvatarRenderInfo") << "Avatar render info POST error: "
- << error[KEY_IDENTIFIER]
- << ": " << error[KEY_MESSAGE]
- << " from region " << regionp->getName()
- << LL_ENDL;
- }
+ 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
}
- else
- {
- LL_INFOS("AvatarRenderInfo") << "Avatar render weight POST result recieved but region not found for "
- << mRegionHandle << LL_ENDL;
- }
- }
-
-private:
- U64 mRegionHandle;
};
-// static
// Send request for one region, no timer checks
+// called when the
void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regionp)
{
- std::string url = regionp->getCapability("AvatarRenderInfo");
- if (!url.empty())
+ if ( regionp->getRenderInfoReportTimer().hasExpired() ) // Time to make request
{
- LL_DEBUGS("AvatarRenderInfo") << "LRI: Checking for avatar render info to send to region "
- << regionp->getName()
- << " from " << url
- << LL_ENDL;
-
- // Build the render info to POST to the region
- LLSD report = LLSD::emptyMap();
- LLSD agents = LLSD::emptyMap();
-
- std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
- while( iter != LLCharacter::sInstances.end() )
+ U32 num_avs = 0;
+
+ std::string url = regionp->getCapability("AvatarRenderInfo");
+ if (!url.empty())
{
- 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
+ // 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() )
{
- avatar->calculateUpdateRenderCost(); // Make sure the numbers are up-to-date
-
- LLSD info = LLSD::emptyMap();
- if (avatar->getVisualComplexity() > 0)
+ 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
{
- info[KEY_WEIGHT] = avatar->getVisualComplexity();
- agents[avatar->getID().asString()] = info;
+ avatar->calculateUpdateRenderCost(); // Make sure the numbers are up-to-date
- LL_DEBUGS("AvatarRenderInfo") << "LRI: Sending avatar render info for " << avatar->getID()
- << ": " << info << LL_ENDL;
+ LLSD info = LLSD::emptyMap();
+ if (avatar->getVisualComplexity() > 0)
+ {
+ info[KEY_WEIGHT] = avatar->getVisualComplexity();
+ agents[avatar->getID().asString()] = info;
+
+ LL_DEBUGS("AvatarRenderInfo") << "Sending avatar render info for " << avatar->getID()
+ << ": " << info << LL_ENDL;
+ num_avs++;
+ }
}
+ iter++;
}
- iter++;
- }
- report[KEY_AGENTS] = agents;
- if (agents.size() > 0)
+ 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_INFOS("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_INFOS("AvatarRenderInfo") << "LRI: Sending info for " << agents.size()
- << " avatars to region " << regionp->getName()
- << LL_ENDL;
- LLHTTPClient::post(url, report, new LLAvatarRenderInfoPostResponder(regionp->getHandle()));
+ 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));
}
}
@@ -285,16 +320,39 @@ void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regio
// Send request for one region, no timer checks
void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regionp)
{
- std::string url = regionp->getCapability("AvatarRenderInfo");
- if (!url.empty())
+ if (regionp->getRenderInfoRequestTimer().hasExpired())
{
- LL_DEBUGS("AvatarRenderInfo") << "LRI: Requesting avatar render info for region "
- << regionp->getName()
- << " from " << url
- << LL_ENDL;
+ 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_INFOS("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;
+ }
- // First send a request to get the latest data
- LLHTTPClient::get(url, new LLAvatarRenderInfoGetResponder(regionp->getHandle()));
+ regionp->getRenderInfoRequestTimer().resetWithExpiry(SECS_BETWEEN_REGION_REQUEST);
}
}
@@ -303,56 +361,60 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi
// Called every frame - send render weight requests to every region
void LLAvatarRenderInfoAccountant::idle()
{
- if (sRenderInfoReportTimer.hasExpired())
- {
- const F32 SECS_BETWEEN_REGION_SCANS = 5.f; // Scan the region list every 5 seconds
- const F32 SECS_BETWEEN_REGION_REQUEST = 60.0; // Update each region every 60 seconds
+ mHttpRequest->update(0); // give any pending http operations a chance to call completion methods
- S32 num_avs = LLCharacter::sInstances.size();
-
- LL_DEBUGS("AvatarRenderInfo") << "LRI: Scanning all regions and checking for render info updates"
+ if (mRenderInfoScanTimer.hasExpired())
+ {
+ LL_DEBUGS("AvatarRenderInfo") << "Scanning regions for render info updates"
<< LL_ENDL;
- // Check all regions and see if it's time to fetch/send data
+ // Check all regions
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
- iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
+ iter != LLWorld::getInstance()->getRegionList().end();
+ ++iter)
{
LLViewerRegion* regionp = *iter;
- if (regionp &&
- regionp->isAlive() &&
- regionp->capabilitiesReceived() && // Region has capability URLs available
- regionp->getRenderInfoRequestTimer().hasExpired()) // Time to make request
+ if ( regionp
+ && regionp->isAlive()
+ && regionp->capabilitiesReceived())
{
+ // each of these is further governed by and resets its own timer
sendRenderInfoToRegion(regionp);
getRenderInfoFromRegion(regionp);
-
- // Reset this regions timer, moving to longer intervals if there are lots of avatars around
- regionp->getRenderInfoRequestTimer().resetWithExpiry(SECS_BETWEEN_REGION_REQUEST + (2.f * num_avs));
}
}
// We scanned all the regions, reset the request timer.
- sRenderInfoReportTimer.resetWithExpiry(SECS_BETWEEN_REGION_SCANS);
+ mRenderInfoScanTimer.resetWithExpiry(SECS_BETWEEN_REGION_SCANS);
}
}
+void LLAvatarRenderInfoAccountant::resetRenderInfoScanTimer()
+{
+ // this will force the next frame to rescan
+ mRenderInfoScanTimer.reset();
+}
// static
-// Make sRenderInfoReportTimer expire so the next call to idle() will scan and query a new region
-// called via LLViewerRegion::setCapabilitiesReceived() boost signals when the capabilities
+// Called via LLViewerRegion::setCapabilitiesReceived() boost signals when the capabilities
// are returned for a new LLViewerRegion, and is the earliest time to get render info
-void LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer(const LLUUID& region_id)
+void LLAvatarRenderInfoAccountant::scanNewRegion(const LLUUID& region_id)
{
- LL_INFOS("AvatarRenderInfo") << "LRI: Viewer has new region capabilities, clearing global render info timer"
- << " and timer for region " << region_id
- << LL_ENDL;
+ LL_INFOS("AvatarRenderInfo") << region_id << LL_ENDL;
- // Reset the global timer so it will scan regions immediately
- sRenderInfoReportTimer.reset();
+ // Reset the global timer so it will scan regions on the next call to ::idle
+ LLAvatarRenderInfoAccountant::getInstance()->resetRenderInfoScanTimer();
LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id);
if (regionp)
- { // Reset the region's timer so it will request data immediately
+ { // Reset the region's timers so we will:
+ // * request render info from it immediately
+ // * report on the following scan
regionp->getRenderInfoRequestTimer().reset();
+ regionp->getRenderInfoReportTimer().resetWithExpiry(SECS_BETWEEN_REGION_SCANS);
+ }
+ else
+ {
+ LL_WARNS("AvatarRenderInfo") << "unable to resolve region "<<region_id<<LL_ENDL;
}
}