Added LL_WARNS_IF to llerror.h

If the coro is given something other than a map from the http then move the return into a body section.
Changed windlight to use a coroutine and the new LLCore::Http libarary.
Extra comments into Event Polling.
meow-7.2.2
Rider Linden 2015-04-09 16:46:41 -07:00
parent fb082a185d
commit e28a5b6ead
5 changed files with 165 additions and 123 deletions

View File

@ -354,6 +354,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
#define LL_WARNS(...) lllog(LLError::LEVEL_WARN, false, ##__VA_ARGS__)
#define LL_ERRS(...) lllog(LLError::LEVEL_ERROR, false, ##__VA_ARGS__)
// alternative to llassert_always that prints explanatory message
#define LL_WARNS_IF(exp, ...) if (exp) LL_WARNS(##__VA_ARGS__) << "(" #exp ")"
#define LL_ERRS_IF(exp, ...) if (exp) LL_ERRS(##__VA_ARGS__) << "(" #exp ")"
// Only print the log message once (good for warnings or infos that would otherwise

View File

@ -241,12 +241,19 @@ void HttpCoroHandler::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRespons
}
if (result.isUndefined())
{
// If we've gotten to this point and the result LLSD is still undefined
{ // If we've gotten to this point and the result LLSD is still undefined
// either there was an issue deserializing the body or the response was
// blank. Create an empty map to hold the result either way.
result = LLSD::emptyMap();
}
else if (!result.isMap())
{ // The results are not themselves a map. Move them down so that
// this method can return a map to the caller.
// *TODO: Should it always do this?
LLSD newResult = LLSD::emptyMap();
newResult["content"] = result;
result = newResult;
}
}
buildStatusEntry(response, status, result);

View File

@ -59,11 +59,11 @@ namespace Details
// We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error.
// This means we attempt to recover relatively quickly but back off giving more time to recover
// until we finally give up after MAX_EVENT_POLL_HTTP_ERRORS attempts.
static const F32 EVENT_POLL_ERROR_RETRY_SECONDS;
static const F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC;
static const S32 MAX_EVENT_POLL_HTTP_ERRORS;
static const F32 EVENT_POLL_ERROR_RETRY_SECONDS;
static const F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC;
static const S32 MAX_EVENT_POLL_HTTP_ERRORS;
void eventPollCoro(LLCoros::self& self, std::string url);
void eventPollCoro(LLCoros::self& self, std::string url);
void handleMessage(const LLSD &content);
@ -138,11 +138,14 @@ namespace Details
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EventPoller", mHttpPolicy));
LLSD acknowledge;
int errorCount = 0;
int counter = mCounter; // saved on the stack for debugging.
int counter = mCounter; // saved on the stack for logging.
LL_INFOS("LLEventPollImpl") << " <" << counter << "> entering coroutine." << LL_ENDL;
mAdapter = httpAdapter;
// continually poll for a server update until we've been flagged as
// finished
while (!mDone)
{
LLSD request;
@ -158,23 +161,23 @@ namespace Details
// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = "
// << LLSDXMLStreamer(result) << LL_ENDL;
LLSD httpResults;
httpResults = result["http_result"];
LLSD httpResults = result["http_result"];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults);
if (!status)
{
if (status == LLCore::HttpStatus(HTTP_BAD_GATEWAY))
{
// A HTTP_BAD_GATEWAY (502) error is our standard timeout response
{ // A HTTP_BAD_GATEWAY (502) error is our standard timeout response
// we get this when there are no events.
errorCount = 0;
continue;
}
else if ((status == LLCore::HttpStatus(LLCore::HttpStatus::LLCORE, LLCore::HE_OP_CANCELED)) ||
(status == LLCore::HttpStatus(HTTP_NOT_FOUND)))
{
{ // Event polling for this server has been canceled. In
// some cases the server gets ahead of the viewer and will
// return a 404 error (Not Found) before the cancel event
// comes back in the queue
LL_WARNS() << "Canceling coroutine" << LL_ENDL;
break;
}
@ -182,7 +185,11 @@ namespace Details
<< status.toTerseString() << ": '" << httpResults["message"] << "'" << LL_ENDL;
if (errorCount < MAX_EVENT_POLL_HTTP_ERRORS)
{
{ // An unanticipated error has been received from our poll
// request. Calculate a timeout and wait for it to expire(sleep)
// before trying again. The sleep time is increased by 5 seconds
// for each consecutive error.
LLEventTimeout timeout;
++errorCount;
F32 waitToRetry = EVENT_POLL_ERROR_RETRY_SECONDS
@ -191,15 +198,12 @@ namespace Details
LL_WARNS("LLEventPollImpl") << "<" << counter << "> Retrying in " << waitToRetry <<
" seconds, error count is now " << errorCount << LL_ENDL;
{
LLEventTimeout timeout;
timeout.eventAfter(waitToRetry, LLSD());
waitForEventOn(self, timeout);
}
timeout.eventAfter(waitToRetry, LLSD());
waitForEventOn(self, timeout);
if (mDone)
break;
LL_INFOS("LLEventPollImpl") << "<" << counter << "> About to retry request." << LL_ENDL;
continue;
}
else
@ -208,7 +212,6 @@ namespace Details
// IMs, teleports, about land, selecting land, region crossing and more will all fail.
// They are essentially disconnected from the region even though some things may still work.
// Since things won't get better until they relog we force a disconnect now.
mDone = true;
// *NOTE:Mani - The following condition check to see if this failing event poll
@ -237,10 +240,7 @@ namespace Details
acknowledge = result["id"];
LLSD events = result["events"];
if (acknowledge.isUndefined())
{
LL_WARNS("LLEventPollImpl") << " id undefined" << LL_ENDL;
}
LL_WARNS_IF((acknowledge.isUndefined()), "LLEventPollImpl") << " id undefined" << LL_ENDL;
// was LL_INFOS() but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG
LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> " << events.size() << "events (id " << LLSDXMLStreamer(acknowledge) << ")" << LL_ENDL;
@ -256,7 +256,6 @@ namespace Details
}
}
LL_INFOS("LLEventPollImpl") << " <" << counter << "> Leaving coroutine." << LL_ENDL;
}
}

View File

@ -32,6 +32,7 @@
#include "llviewerregion.h"
#include "llenvmanager.h"
#include "llnotificationsutil.h"
#include "llcorehttputil.h"
/****
* LLEnvironmentRequest
@ -81,55 +82,62 @@ bool LLEnvironmentRequest::doRequest()
return false;
}
LL_INFOS("WindlightCaps") << "Requesting region windlight settings via " << url << LL_ENDL;
LLHTTPClient::get(url, new LLEnvironmentRequestResponder());
return true;
std::string coroname =
LLCoros::instance().launch("LLEnvironmentRequest::environmentRequestCoro",
boost::bind(&LLEnvironmentRequest::environmentRequestCoro, _1, url));
LL_INFOS("WindlightCaps") << "Requesting region windlight settings via " << url << LL_ENDL;
return true;
}
/****
* LLEnvironmentRequestResponder
****/
int LLEnvironmentRequestResponder::sCount = 0; // init to 0
S32 LLEnvironmentRequest::sLastRequest = 0;
LLEnvironmentRequestResponder::LLEnvironmentRequestResponder()
//static
void LLEnvironmentRequest::environmentRequestCoro(LLCoros::self& self, std::string url)
{
mID = ++sCount;
}
/*virtual*/ void LLEnvironmentRequestResponder::httpSuccess()
{
const LLSD& unvalidated_content = getContent();
LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL;
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
S32 requestId = ++LLEnvironmentRequest::sLastRequest;
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentRequest", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
if (mID != sCount)
{
LL_INFOS("WindlightCaps") << "Got superseded by another responder; ignoring..." << LL_ENDL;
return;
}
LLSD result = httpAdapter->getAndYield(self, httpRequest, url);
LLUUID regionId;
if( gAgent.getRegion() )
{
regionId = gAgent.getRegion()->getRegionID();
}
if (unvalidated_content[0]["regionID"].asUUID() != regionId )
{
LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting "
<< regionId << " but got " << unvalidated_content[0]["regionID"].asUUID()
<< ") - ignoring..." << LL_ENDL;
return;
}
if (requestId != LLEnvironmentRequest::sLastRequest)
{
LL_INFOS("WindlightCaps") << "Got superseded by another responder; ignoring..." << LL_ENDL;
return;
}
LLEnvManagerNew::getInstance()->onRegionSettingsResponse(unvalidated_content);
}
/*virtual*/
void LLEnvironmentRequestResponder::httpFailure()
{
LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... "
<< dumpResponse() << LL_ENDL;
LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD());
LLSD httpResults = result["http_result"];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults);
if (!status)
{
LL_WARNS("WindlightCaps") << "Got an error, not using region windlight... " << LL_ENDL;
LLEnvManagerNew::getInstance()->onRegionSettingsResponse(LLSD());
return;
}
result = result["content"];
LL_INFOS("WindlightCaps") << "Received region windlight settings" << LL_ENDL;
LLUUID regionId;
if (gAgent.getRegion())
{
regionId = gAgent.getRegion()->getRegionID();
}
if (result[0]["regionID"].asUUID() != regionId)
{
LL_WARNS("WindlightCaps") << "Not in the region from where this data was received (wanting "
<< regionId << " but got " << result[0]["regionID"].asUUID()
<< ") - ignoring..." << LL_ENDL;
return;
}
LLEnvManagerNew::getInstance()->onRegionSettingsResponse(result);
}
/****
* LLEnvironmentApply
****/
@ -161,53 +169,86 @@ bool LLEnvironmentApply::initiateRequest(const LLSD& content)
return false;
}
LL_INFOS("WindlightCaps") << "Sending windlight settings to " << url << LL_ENDL;
LL_DEBUGS("WindlightCaps") << "content: " << content << LL_ENDL;
LLHTTPClient::post(url, content, new LLEnvironmentApplyResponder());
LL_INFOS("WindlightCaps") << "Sending windlight settings to " << url << LL_ENDL;
LL_DEBUGS("WindlightCaps") << "content: " << content << LL_ENDL;
std::string coroname =
LLCoros::instance().launch("LLEnvironmentApply::environmentApplyCoro",
boost::bind(&LLEnvironmentApply::environmentApplyCoro, _1, url, content));
return true;
}
/****
* LLEnvironmentApplyResponder
****/
/*virtual*/ void LLEnvironmentApplyResponder::httpSuccess()
void LLEnvironmentApply::environmentApplyCoro(LLCoros::self& self, std::string url, LLSD content)
{
const LLSD& content = getContent();
if (!content.isMap() || !content.has("regionID"))
{
failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content);
return;
}
if (content["regionID"].asUUID() != gAgent.getRegion()->getRegionID())
{
LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently "
<< gAgent.getRegion()->getRegionID() << ", reply is from " << content["regionID"].asUUID()
<< "); ignoring..." << LL_ENDL;
return;
}
else if (content["success"].asBoolean())
{
LL_DEBUGS("WindlightCaps") << "Success in applying windlight settings to region " << content["regionID"].asUUID() << LL_ENDL;
LLEnvManagerNew::instance().onRegionSettingsApplyResponse(true);
}
else
{
LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings! " << dumpResponse() << LL_ENDL;
LLSD args(LLSD::emptyMap());
args["FAIL_REASON"] = content["fail_reason"].asString();
LLNotificationsUtil::add("WLRegionApplyFail", args);
LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false);
}
}
/*virtual*/
void LLEnvironmentApplyResponder::httpFailure()
{
LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! "
<< dumpResponse() << LL_ENDL;
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EnvironmentApply", httpPolicy));
LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest);
LLSD args(LLSD::emptyMap());
std::stringstream msg;
msg << getReason() << " (Code " << getStatus() << ")";
args["FAIL_REASON"] = msg.str();
LLNotificationsUtil::add("WLRegionApplyFail", args);
LLSD result = httpAdapter->postAndYield(self, httpRequest, url, content);
LLSD notify; // for error reporting. If there is something to report to user this will be defined.
/*
* Expecting reply from sim in form of:
* {
* regionID : uuid,
* messageID: uuid,
* success : true
* }
* or
* {
* regionID : uuid,
* success : false,
* fail_reason : string
* }
*/
do // while false.
{ // Breaks from loop in the case of an error.
LLSD httpResults = result["http_result"];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults);
if (!status)
{
LL_WARNS("WindlightCaps") << "Couldn't apply windlight settings to region! " << LL_ENDL;
std::stringstream msg;
msg << status.toString() << " (Code " << status.toTerseString() << ")";
notify = LLSD::emptyMap();
notify["FAIL_REASON"] = msg.str();
break;
}
if (!result.has("regionID"))
{
notify = LLSD::emptyMap();
notify["FAIL_REASON"] = "Missing regionID, malformed response";
break;
}
else if (result["regionID"].asUUID() != gAgent.getRegion()->getRegionID())
{
// note that there is no report to the user in this failure case.
LL_WARNS("WindlightCaps") << "No longer in the region where data was sent (currently "
<< gAgent.getRegion()->getRegionID() << ", reply is from " << result["regionID"].asUUID()
<< "); ignoring..." << LL_ENDL;
break;
}
else if (!result["success"].asBoolean())
{
LL_WARNS("WindlightCaps") << "Region couldn't apply windlight settings! " << LL_ENDL;
notify = LLSD::emptyMap();
notify["FAIL_REASON"] = result["fail_reason"].asString();
break;
}
LL_DEBUGS("WindlightCaps") << "Success in applying windlight settings to region " << result["regionID"].asUUID() << LL_ENDL;
LLEnvManagerNew::instance().onRegionSettingsApplyResponse(true);
} while (false);
if (!notify.isUndefined())
{
LLNotificationsUtil::add("WLRegionApplyFail", notify);
LLEnvManagerNew::instance().onRegionSettingsApplyResponse(false);
}
}

View File

@ -29,6 +29,7 @@
#include "llviewerprecompiledheaders.h"
#include "llhttpclient.h"
#include "llcoros.h"
class LLEnvironmentRequest
{
@ -40,21 +41,10 @@ public:
private:
static void onRegionCapsReceived(const LLUUID& region_id);
static bool doRequest();
};
class LLEnvironmentRequestResponder: public LLHTTPClient::Responder
{
LOG_CLASS(LLEnvironmentRequestResponder);
private:
/* virtual */ void httpSuccess();
/* virtual */ void httpFailure();
static void environmentRequestCoro(LLCoros::self& self, std::string url);
private:
friend class LLEnvironmentRequest;
LLEnvironmentRequestResponder();
static int sCount;
int mID;
static S32 sLastRequest;
};
class LLEnvironmentApply
@ -67,8 +57,11 @@ public:
private:
static clock_t sLastUpdate;
static clock_t UPDATE_WAIT_SECONDS;
static void environmentApplyCoro(LLCoros::self& self, std::string url, LLSD content);
};
#if 0
class LLEnvironmentApplyResponder: public LLHTTPClient::Responder
{
LOG_CLASS(LLEnvironmentApplyResponder);
@ -97,5 +90,6 @@ private:
LLEnvironmentApplyResponder() {}
};
#endif
#endif // LL_LLWLHANDLERS_H