diff options
| author | Don Kjer <don@lindenlab.com> | 2013-03-13 06:26:25 +0000 |
|---|---|---|
| committer | Don Kjer <don@lindenlab.com> | 2013-03-13 06:26:25 +0000 |
| commit | f945415210f0e18c2c6d941fda6b7d45cb0f06f1 (patch) | |
| tree | cf93ca0d9596a82a8fc7a4d1b1f0ee263ea5549e /indra/newview/llappearancemgr.cpp | |
| parent | 54cdc322b8f2bd35b289cacf3493622e7cc51194 (diff) | |
Large changes to the LLCurl::Responder API, as well as pulling in some changes to common libraries from the server codebase:
* Additional error checking in http handlers.
* Uniform log spam for http errors.
* Switch to using constants for http heads and status codes.
* Fixed bugs in incorrectly checking if parsing LLSD xml resulted in an error.
* Reduced spam regarding LLSD parsing errors in the default completedRaw http handler. It should not longer be necessary to short-circuit completedRaw to avoid spam.
* Ported over a few bug fixes from the server code.
* Switch mode http status codes to use S32 instead of U32.
* Ported LLSD::asStringRef from server code; avoids copying strings all over the place.
* Ported server change to LLSD::asBinary; this always returns a reference now instead of copying the entire binary blob.
* Ported server pretty notation format (and pretty binary format) to llsd serialization.
* The new LLCurl::Responder API no longer has two error handlers to choose from. Overriding the following methods have been deprecated:
** error - use httpFailure
** errorWithContent - use httpFailure
** result - use httpSuccess
** completed - use httpCompleted
** completedHeader - no longer necessary; call getResponseHeaders() from a completion method to obtain these headers.
* In order to 'catch' a completed http request, override one of these methods:
** httpSuccess - Called for any 2xx status code.
** httpFailure - Called for any non-2xx status code.
** httpComplete - Called for all status codes. Default implementation is to call either httpSuccess or httpFailure.
* It is recommended to keep these methods protected/private in order to avoid triggering of these methods without using a 'push' method (see below).
* Uniform error handling should followed whenever possible by calling a variant of this during httpFailure:
** llwarns << dumpResponse() << llendl;
* Be sure to include LOG_CLASS(your_class_name) in your class in order for the log entry to give more context.
* In order to 'push' a result into the responder, you should no longer call error, errorWithContent, result, or completed.
* Nor should you directly call httpSuccess/Failure/Completed (unless passing a message up to a parent class).
* Instead, you can set the internal content of a responder and trigger a corresponding method using the following methods:
** successResult - Sets results and calls httpSuccess
** failureResult - Sets results and calls httpFailure
** completedResult - Sets results and calls httpCompleted
* To obtain information about a the response from a reponder method, use the following getters:
** getStatus - HTTP status code
** getReason - Reason string
** getContent - Content (Parsed body LLSD)
** getResponseHeaders - Response Headers (LLSD map)
** getHTTPMethod - HTTP method of the request
** getURL - URL of the request
* It is still possible to override completeRaw if you want to manipulate data directly out of LLPumpIO.
* See indra/llmessage/llcurl.h for more information.
Diffstat (limited to 'indra/newview/llappearancemgr.cpp')
| -rwxr-xr-x | indra/newview/llappearancemgr.cpp | 83 |
1 files changed, 60 insertions, 23 deletions
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 2c76efc7fb..92a896a3c2 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -2984,20 +2984,23 @@ class LLHTTPRetryPolicy: public LLThreadSafeRefCount public: LLHTTPRetryPolicy() {} virtual ~LLHTTPRetryPolicy() {} - virtual bool shouldRetry(U32 status, F32& seconds_to_wait) = 0; + virtual bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) = 0; }; // Example of simplest possible policy, not necessarily recommended. +// This would be a potentially dangerous policy to enable. Removing for now: +#if 0 class LLAlwaysRetryImmediatelyPolicy: public LLHTTPRetryPolicy { public: LLAlwaysRetryImmediatelyPolicy() {} - bool shouldRetry(U32 status, F32& seconds_to_wait) + bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) { seconds_to_wait = 0.0; return true; } }; +#endif // Very general policy with geometric back-off after failures, // up to a maximum delay, and maximum number of retries. @@ -3014,10 +3017,25 @@ public: { } - bool shouldRetry(U32 status, F32& seconds_to_wait) + bool shouldRetry(S32 status, const LLSD& headers, F32& seconds_to_wait) { - seconds_to_wait = mDelay; - mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); +#if 0 + // *TODO: Test using status codes to only retry server errors. + // Only server errors would potentially return a different result on retry. + if (!isHttpServerErrorStatus(status)) return false; +#endif + +#if 0 + // *TODO: Honor server Retry-After header. + // Status 503 may ask us to wait for a certain amount of time before retrying. + if (!headers.has(HTTP_HEADER_RETRY_AFTER) + || !getSecondsUntilRetryAfter(headers[HTTP_HEADER_RETRY_AFTER].asStringRef(), seconds_to_wait)) +#endif + { + seconds_to_wait = mDelay; + mDelay = llclamp(mDelay*mBackoffFactor,mMinDelay,mMaxDelay); + } + mRetryCount++; return (mRetryCount<=mMaxRetries); } @@ -3033,6 +3051,7 @@ private: class RequestAgentUpdateAppearanceResponder: public LLHTTPClient::Responder { + LOG_CLASS(RequestAgentUpdateAppearanceResponder); public: RequestAgentUpdateAppearanceResponder() { @@ -3043,13 +3062,19 @@ public: { } +protected: // Successful completion. - /* virtual */ void result(const LLSD& content) + /* virtual */ void httpSuccess() { - LL_DEBUGS("Avatar") << "content: " << ll_pretty_print_sd(content) << LL_ENDL; + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } if (content["success"].asBoolean()) { - LL_DEBUGS("Avatar") << "OK" << LL_ENDL; + LL_DEBUGS("Avatar") << dumpResponse() << LL_ENDL; if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_ok", content); @@ -3057,33 +3082,35 @@ public: } else { - onFailure(200); + failureResult(HTTP_INTERNAL_ERROR, "Non-success response", content); } } // Error - /*virtual*/ void errorWithContent(U32 status, const std::string& reason, const LLSD& content) + /*virtual*/ void httpFailure() { - llwarns << "appearance update request failed, status: " << status << " reason: " << reason << " code: " << content["code"].asInteger() << " error: \"" << content["error"].asString() << "\"" << llendl; + const LLSD& content = getContent(); + LL_WARNS("Avatar") << "appearance update request failed " + << dumpResponse() << LL_ENDL; if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { dumpContents(gAgentAvatarp->getFullname() + "_appearance_request_error", content); debugCOF(content); } - onFailure(status); - } + onFailure(); + } - void onFailure(U32 status) + void onFailure() { F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(status,seconds_to_wait)) + if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait)) { llinfos << "retrying" << llendl; doAfterInterval(boost::bind(&LLAppearanceMgr::requestServerAppearanceUpdate, LLAppearanceMgr::getInstance(), - LLCurl::ResponderPtr(this)), - seconds_to_wait); + LLHTTPClient::ResponderPtr(this)), + seconds_to_wait); } else { @@ -3286,6 +3313,7 @@ void LLAppearanceMgr::requestServerAppearanceUpdate(LLCurl::ResponderPtr respond class LLIncrementCofVersionResponder : public LLHTTPClient::Responder { + LOG_CLASS(LLIncrementCofVersionResponder); public: LLIncrementCofVersionResponder() : LLHTTPClient::Responder() { @@ -3296,10 +3324,17 @@ public: { } - virtual void result(const LLSD &pContent) +protected: + virtual void httpSuccess() { llinfos << "Successfully incremented agent's COF." << llendl; - S32 new_version = pContent["category"]["version"].asInteger(); + const LLSD& content = getContent(); + if (!content.isMap()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + S32 new_version = content["category"]["version"].asInteger(); LLAppearanceMgr* app_mgr = LLAppearanceMgr::getInstance(); @@ -3308,12 +3343,13 @@ public: app_mgr->mLastUpdateRequestCOFVersion = new_version; } - virtual void errorWithContent(U32 pStatus, const std::string& pReason, const LLSD& content) + + virtual void httpFailure() { - llwarns << "While attempting to increment the agent's cof we got an error with [status:" - << pStatus << "]: " << content << llendl; + LL_WARNS("Avatar") << "While attempting to increment the agent's cof we got an error " + << dumpResponse() << LL_ENDL; F32 seconds_to_wait; - if (mRetryPolicy->shouldRetry(pStatus,seconds_to_wait)) + if (mRetryPolicy->shouldRetry(getStatus(), getResponseHeaders(), seconds_to_wait)) { llinfos << "retrying" << llendl; doAfterInterval(boost::bind(&LLAppearanceMgr::incrementCofVersion, @@ -3327,6 +3363,7 @@ public: } } +private: LLPointer<LLHTTPRetryPolicy> mRetryPolicy; }; |
