From 1c91c8a106a78f2087a3fb4312e428a0128283b4 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 8 Apr 2015 10:17:34 -0700 Subject: Adding weak pointer support. Event polling as a coroutine. (incomplete) Groundwork for canceling HttpCoroutineAdapter yields. --- indra/newview/lleventpoll.cpp | 688 +++++++++++++++++++++++++++--------------- 1 file changed, 447 insertions(+), 241 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 4de6ad4d2f..493ee06083 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -37,254 +37,460 @@ #include "llviewerregion.h" #include "message.h" #include "lltrans.h" +#include "llcoros.h" +#include "lleventcoro.h" +#include "llcorehttputil.h" namespace { - // 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. - const F32 EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout. - const F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout. - const S32 MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules. - - class LLEventPollResponder : public LLHTTPClient::Responder - { - LOG_CLASS(LLEventPollResponder); - public: - - static LLHTTPClient::ResponderPtr start(const std::string& pollURL, const LLHost& sender); - void stop(); - - void makeRequest(); - - /* virtual */ void completedRaw(const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer); - - private: - LLEventPollResponder(const std::string& pollURL, const LLHost& sender); - ~LLEventPollResponder(); - - - void handleMessage(const LLSD& content); - - /* virtual */ void httpFailure(); - /* virtual */ void httpSuccess(); - - private: - - bool mDone; - - std::string mPollURL; - std::string mSender; - - LLSD mAcknowledge; - - // these are only here for debugging so we can see which poller is which - static int sCount; - int mCount; - S32 mErrorCount; - }; - - class LLEventPollEventTimer : public LLEventTimer - { - typedef LLPointer EventPollResponderPtr; - - public: - LLEventPollEventTimer(F32 period, EventPollResponderPtr responder) - : LLEventTimer(period), mResponder(responder) - { } - - virtual BOOL tick() - { - mResponder->makeRequest(); - return TRUE; // Causes this instance to be deleted. - } - - private: - - EventPollResponderPtr mResponder; - }; - - //static - LLHTTPClient::ResponderPtr LLEventPollResponder::start( - const std::string& pollURL, const LLHost& sender) - { - LLHTTPClient::ResponderPtr result = new LLEventPollResponder(pollURL, sender); - LL_INFOS() << "LLEventPollResponder::start <" << sCount << "> " - << pollURL << LL_ENDL; - return result; - } - - void LLEventPollResponder::stop() - { - LL_INFOS() << "LLEventPollResponder::stop <" << mCount << "> " - << mPollURL << LL_ENDL; - // there should be a way to stop a LLHTTPClient request in progress - mDone = true; - } - - int LLEventPollResponder::sCount = 0; - - LLEventPollResponder::LLEventPollResponder(const std::string& pollURL, const LLHost& sender) - : mDone(false), - mPollURL(pollURL), - mCount(++sCount), - mErrorCount(0) - { - //extract host and port of simulator to set as sender - LLViewerRegion *regionp = gAgent.getRegion(); - if (!regionp) - { - LL_ERRS() << "LLEventPoll initialized before region is added." << LL_ENDL; - } - mSender = sender.getIPandPort(); - LL_INFOS() << "LLEventPoll initialized with sender " << mSender << LL_ENDL; - makeRequest(); - } - - LLEventPollResponder::~LLEventPollResponder() - { - stop(); - LL_DEBUGS() << "LLEventPollResponder::~Impl <" << mCount << "> " - << mPollURL << LL_ENDL; - } - - // virtual - void LLEventPollResponder::completedRaw(const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) - { - if (getStatus() == HTTP_BAD_GATEWAY) - { - // These errors are not parsable as LLSD, - // which LLHTTPClient::Responder::completedRaw will try to do. - httpCompleted(); - } - else - { - LLHTTPClient::Responder::completedRaw(channels,buffer); - } - } - - void LLEventPollResponder::makeRequest() - { - LLSD request; - request["ack"] = mAcknowledge; - request["done"] = mDone; - - LL_DEBUGS() << "LLEventPollResponder::makeRequest <" << mCount << "> ack = " - << LLSDXMLStreamer(mAcknowledge) << LL_ENDL; - LLHTTPClient::post(mPollURL, request, this); - } - - void LLEventPollResponder::handleMessage(const LLSD& content) - { - std::string msg_name = content["message"]; - LLSD message; - message["sender"] = mSender; - message["body"] = content["body"]; - LLMessageSystem::dispatch(msg_name, message); - } - - //virtual - void LLEventPollResponder::httpFailure() - { - if (mDone) return; - - // A HTTP_BAD_GATEWAY (502) error is our standard timeout response - // we get this when there are no events. - if ( getStatus() == HTTP_BAD_GATEWAY ) - { - mErrorCount = 0; - makeRequest(); - } - else if (mErrorCount < MAX_EVENT_POLL_HTTP_ERRORS) - { - ++mErrorCount; - - // The 'tick' will return TRUE causing the timer to delete this. - new LLEventPollEventTimer(EVENT_POLL_ERROR_RETRY_SECONDS - + mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC - , this); - - LL_WARNS() << dumpResponse() << LL_ENDL; - } - else - { - LL_WARNS() << dumpResponse() - << " [count:" << mCount << "] " - << (mDone ? " -- done" : "") << LL_ENDL; - stop(); - - // At this point we have given up and the viewer will not receive HTTP messages from the simulator. - // IMs, teleports, about land, selecing 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. - - // *NOTE:Mani - The following condition check to see if this failing event poll - // is attached to the Agent's main region. If so we disconnect the viewer. - // Else... its a child region and we just leave the dead event poll stopped and - // continue running. - if(gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSender) - { - LL_WARNS() << "Forcing disconnect due to stalled main region event poll." << LL_ENDL; - LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection")); - } - } - } - - //virtual - void LLEventPollResponder::httpSuccess() - { - LL_DEBUGS() << "LLEventPollResponder::result <" << mCount << ">" - << (mDone ? " -- done" : "") << LL_ENDL; - - if (mDone) return; - - mErrorCount = 0; - - const LLSD& content = getContent(); - if (!content.isMap() || - !content.get("events") || - !content.get("id")) - { - LL_WARNS() << "received event poll with no events or id key: " << dumpResponse() << LL_ENDL; - makeRequest(); - return; - } - - mAcknowledge = content["id"]; - LLSD events = content["events"]; - - if(mAcknowledge.isUndefined()) - { - LL_WARNS() << "LLEventPollResponder: 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() << "LLEventPollResponder::httpSuccess <" << mCount << "> " << events.size() << "events (id " - << LLSDXMLStreamer(mAcknowledge) << ")" << LL_ENDL; - - LLSD::array_const_iterator i = events.beginArray(); - LLSD::array_const_iterator end = events.endArray(); - for (; i != end; ++i) - { - if (i->has("message")) - { - handleMessage(*i); - } - } - - makeRequest(); - } + // 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. + const F32 EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout. + const F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout. + const S32 MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules. + +#if 1 + + class LLEventPollImpl + { + public: + LLEventPollImpl(const LLHost &sender); + + void start(const std::string &url); + void stop(); + private: + void eventPollCoro(LLCoros::self& self, std::string url); + + void handleMessage(const LLSD &content); + + bool mDone; + LLCore::HttpRequest::ptr_t mHttpRequest; + LLCore::HttpRequest::policy_t mHttpPolicy; + std::string mSenderIp; + int mCounter; + + static int sNextCounter; + }; + + + int LLEventPollImpl::sNextCounter = 1; + + + LLEventPollImpl::LLEventPollImpl(const LLHost &sender) : + mDone(false), + mHttpRequest(), + mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID), + mSenderIp(), + mCounter(sNextCounter++) + + { + mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest); + mSenderIp = sender.getIPandPort(); + } + + void LLEventPollImpl::handleMessage(const LLSD& content) + { + std::string msg_name = content["message"]; + LLSD message; + message["sender"] = mSenderIp; + message["body"] = content["body"]; + LLMessageSystem::dispatch(msg_name, message); + } + + void LLEventPollImpl::start(const std::string &url) + { + if (!url.empty()) + { + std::string coroname = + LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro", + boost::bind(&LLEventPollImpl::eventPollCoro, this, _1, url)); + LL_DEBUGS() << coroname << " with url '" << url << LL_ENDL; + } + } + + void LLEventPollImpl::stop() + { + mDone = true; + } + + void LLEventPollImpl::eventPollCoro(LLCoros::self& self, std::string url) + { + LLCoreHttpUtil::HttpCoroutineAdapter httpAdapter("EventPoller", mHttpPolicy); + LLSD acknowledge; + int errorCount = 0; + int counter = mCounter; // saved on the stack for debugging. + + LL_INFOS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> entering coroutine." << LL_ENDL; + + while (!mDone) + { + LLSD request; + request["ack"] = acknowledge; + request["done"] = mDone; + +// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> request = " +// << LLSDXMLStreamer(request) << LL_ENDL; + + LL_INFOS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> posting and yielding." << LL_ENDL; + LLSD result = httpAdapter.postAndYield(self, mHttpRequest, url, request); + +// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = " +// << LLSDXMLStreamer(result) << LL_ENDL; + + if (mDone) + break; + + LLSD httpResults; + httpResults = result["http_result"]; + + + if (!httpResults["success"].asBoolean()) + { + LL_WARNS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code " + << httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL; + + if (httpResults["status"].asInteger() == HTTP_BAD_GATEWAY) + { + // A HTTP_BAD_GATEWAY (502) error is our standard timeout response + // we get this when there are no events. + errorCount = 0; + continue; + } + + LL_WARNS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> " << LLSDXMLStreamer(result) << (mDone ? " -- done" : "") << LL_ENDL; + + if (errorCount < MAX_EVENT_POLL_HTTP_ERRORS) + { + ++errorCount; + + // The 'tick' will return TRUE causing the timer to delete this. + int waitToRetry = EVENT_POLL_ERROR_RETRY_SECONDS + + errorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC; + + LL_WARNS() << "Retrying in " << waitToRetry << + " seconds, error count is now " << errorCount << LL_ENDL; + + // *TODO: Wait for a timeout here + // new LLEventPollEventTimer( + // , this); + continue; + } + else + { + // At this point we have given up and the viewer will not receive HTTP messages from the simulator. + // 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 + // is attached to the Agent's main region. If so we disconnect the viewer. + // Else... its a child region and we just leave the dead event poll stopped and + // continue running. + if (gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSenderIp) + { + LL_WARNS("LLEventPollImpl::eventPollCoro") << "< " << counter << "> Forcing disconnect due to stalled main region event poll." << LL_ENDL; + LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection")); + } + break; + } + } + + LL_DEBUGS("LLEventPollImpl::eventPollCoro") << " <" << counter << ">" + << (mDone ? " -- done" : "") << LL_ENDL; + + errorCount = 0; + + if (!result.isMap() || + !result.get("events") || + !result.get("id")) + { + LL_WARNS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> received event poll with no events or id key: " << LLSDXMLStreamer(result) << LL_ENDL; + continue; + } + + acknowledge = result["id"]; + LLSD events = result["events"]; + + if (acknowledge.isUndefined()) + { + LL_WARNS("LLEventPollImpl::eventPollCoro") << " 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() << "LLEventPollResponder::httpSuccess <" << counter << "> " << events.size() << "events (id " + << LLSDXMLStreamer(acknowledge) << ")" << LL_ENDL; + + LLSD::array_const_iterator i = events.beginArray(); + LLSD::array_const_iterator end = events.endArray(); + for (; i != end; ++i) + { + if (i->has("message")) + { + handleMessage(*i); + } + } + } + LL_INFOS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> Leaving coroutine." << LL_ENDL; + + } + +#else + class LLEventPollResponder : public LLHTTPClient::Responder + { + LOG_CLASS(LLEventPollResponder); + public: + + static LLHTTPClient::ResponderPtr start(const std::string& pollURL, const LLHost& sender); + void stop(); + + void makeRequest(); + + /* virtual */ void completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + + private: + LLEventPollResponder(const std::string& pollURL, const LLHost& sender); + ~LLEventPollResponder(); + + + void handleMessage(const LLSD& content); + + /* virtual */ void httpFailure(); + /* virtual */ void httpSuccess(); + + private: + + bool mDone; + + std::string mPollURL; + std::string mSender; + + LLSD mAcknowledge; + + // these are only here for debugging so we can see which poller is which + static int sCount; + int mCount; + S32 mErrorCount; + }; + + class LLEventPollEventTimer : public LLEventTimer + { + typedef LLPointer EventPollResponderPtr; + + public: + LLEventPollEventTimer(F32 period, EventPollResponderPtr responder) + : LLEventTimer(period), mResponder(responder) + { } + + virtual BOOL tick() + { + mResponder->makeRequest(); + return TRUE; // Causes this instance to be deleted. + } + + private: + + EventPollResponderPtr mResponder; + }; + + //static + LLHTTPClient::ResponderPtr LLEventPollResponder::start( + const std::string& pollURL, const LLHost& sender) + { + LLHTTPClient::ResponderPtr result = new LLEventPollResponder(pollURL, sender); + LL_INFOS() << "LLEventPollResponder::start <" << sCount << "> " + << pollURL << LL_ENDL; + return result; + } + + void LLEventPollResponder::stop() + { + LL_INFOS() << "LLEventPollResponder::stop <" << mCount << "> " + << mPollURL << LL_ENDL; + // there should be a way to stop a LLHTTPClient request in progress + mDone = true; + } + + int LLEventPollResponder::sCount = 0; + + LLEventPollResponder::LLEventPollResponder(const std::string& pollURL, const LLHost& sender) + : mDone(false), + mPollURL(pollURL), + mCount(++sCount), + mErrorCount(0) + { + //extract host and port of simulator to set as sender + LLViewerRegion *regionp = gAgent.getRegion(); + if (!regionp) + { + LL_ERRS() << "LLEventPoll initialized before region is added." << LL_ENDL; + } + mSender = sender.getIPandPort(); + LL_INFOS() << "LLEventPoll initialized with sender " << mSender << LL_ENDL; + makeRequest(); + } + + LLEventPollResponder::~LLEventPollResponder() + { + stop(); + LL_DEBUGS() << "LLEventPollResponder::~Impl <" << mCount << "> " + << mPollURL << LL_ENDL; + } + + // virtual + void LLEventPollResponder::completedRaw(const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) + { + if (getStatus() == HTTP_BAD_GATEWAY) + { + // These errors are not parsable as LLSD, + // which LLHTTPClient::Responder::completedRaw will try to do. + httpCompleted(); + } + else + { + LLHTTPClient::Responder::completedRaw(channels,buffer); + } + } + + void LLEventPollResponder::makeRequest() + { + LLSD request; + request["ack"] = mAcknowledge; + request["done"] = mDone; + + LL_DEBUGS() << "LLEventPollResponder::makeRequest <" << mCount << "> ack = " + << LLSDXMLStreamer(mAcknowledge) << LL_ENDL; + LLHTTPClient::post(mPollURL, request, this); + } + + void LLEventPollResponder::handleMessage(const LLSD& content) + { + std::string msg_name = content["message"]; + LLSD message; + message["sender"] = mSender; + message["body"] = content["body"]; + LLMessageSystem::dispatch(msg_name, message); + } + + //virtual + void LLEventPollResponder::httpFailure() + { + if (mDone) return; + + // A HTTP_BAD_GATEWAY (502) error is our standard timeout response + // we get this when there are no events. + if ( getStatus() == HTTP_BAD_GATEWAY ) + { + mErrorCount = 0; + makeRequest(); + } + else if (mErrorCount < MAX_EVENT_POLL_HTTP_ERRORS) + { + ++mErrorCount; + + // The 'tick' will return TRUE causing the timer to delete this. + new LLEventPollEventTimer(EVENT_POLL_ERROR_RETRY_SECONDS + + mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC + , this); + + LL_WARNS() << dumpResponse() << LL_ENDL; + } + else + { + LL_WARNS() << dumpResponse() + << " [count:" << mCount << "] " + << (mDone ? " -- done" : "") << LL_ENDL; + stop(); + + // At this point we have given up and the viewer will not receive HTTP messages from the simulator. + // IMs, teleports, about land, selecing 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. + + // *NOTE:Mani - The following condition check to see if this failing event poll + // is attached to the Agent's main region. If so we disconnect the viewer. + // Else... its a child region and we just leave the dead event poll stopped and + // continue running. + if(gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSender) + { + LL_WARNS() << "Forcing disconnect due to stalled main region event poll." << LL_ENDL; + LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection")); + } + } + } + + //virtual + void LLEventPollResponder::httpSuccess() + { + LL_DEBUGS() << "LLEventPollResponder::result <" << mCount << ">" + << (mDone ? " -- done" : "") << LL_ENDL; + + if (mDone) return; + + mErrorCount = 0; + + const LLSD& content = getContent(); + if (!content.isMap() || + !content.get("events") || + !content.get("id")) + { + LL_WARNS() << "received event poll with no events or id key: " << dumpResponse() << LL_ENDL; + makeRequest(); + return; + } + + mAcknowledge = content["id"]; + LLSD events = content["events"]; + + if(mAcknowledge.isUndefined()) + { + LL_WARNS() << "LLEventPollResponder: 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() << "LLEventPollResponder::httpSuccess <" << mCount << "> " << events.size() << "events (id " + << LLSDXMLStreamer(mAcknowledge) << ")" << LL_ENDL; + + LLSD::array_const_iterator i = events.beginArray(); + LLSD::array_const_iterator end = events.endArray(); + for (; i != end; ++i) + { + if (i->has("message")) + { + handleMessage(*i); + } + } + + makeRequest(); + } } LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender) - : mImpl(LLEventPollResponder::start(poll_url, sender)) - { } + : mImpl(LLEventPollResponder::start(poll_url, sender)) +{ } LLEventPoll::~LLEventPoll() { - LLHTTPClient::Responder* responderp = mImpl.get(); - LLEventPollResponder* event_poll_responder = dynamic_cast(responderp); - if (event_poll_responder) event_poll_responder->stop(); + LLHTTPClient::Responder* responderp = mImpl.get(); + LLEventPollResponder* event_poll_responder = dynamic_cast(responderp); + if (event_poll_responder) event_poll_responder->stop(); +} +#endif +} + +LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender): + mImpl() +{ + mImpl = boost::unique_ptr(new LLEventPollImpl(sender)); + mImpl->start(poll_url); +} + +LLEventPoll::~LLEventPoll() +{ + mImpl->stop(); + } -- cgit v1.2.3 From 93382ee0c0c570e58b17af5f43f9738d773e8add Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 8 Apr 2015 14:29:37 -0700 Subject: Moved some LLEventPolling internal classes to a named namespace Canceling outstanding polling transactions --- indra/newview/lleventpoll.cpp | 50 ++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 17 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 493ee06083..625bbfae0c 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -41,9 +41,11 @@ #include "lleventcoro.h" #include "llcorehttputil.h" -namespace +namespace LLEventPolling { - // We will wait RETRY_SECONDS + (errorCount * RETRY_SECONDS_INC) before retrying after an error. +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. const F32 EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout. @@ -69,6 +71,7 @@ namespace LLCore::HttpRequest::policy_t mHttpPolicy; std::string mSenderIp; int mCounter; + LLCoreHttpUtil::HttpCoroutineAdapter::wptr_t mAdapter; static int sNextCounter; }; @@ -105,24 +108,33 @@ namespace std::string coroname = LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro", boost::bind(&LLEventPollImpl::eventPollCoro, this, _1, url)); - LL_DEBUGS() << coroname << " with url '" << url << LL_ENDL; + LL_INFOS() << coroname << " with url '" << url << LL_ENDL; } } void LLEventPollImpl::stop() { + LL_INFOS() << "requesting stop for event poll coroutine <" << mCounter << ">" << LL_ENDL; mDone = true; + + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t adapter = mAdapter.lock(); + if (adapter) + { + // cancel the yielding operation if any. + adapter->cancelYieldingOperation(); + } } void LLEventPollImpl::eventPollCoro(LLCoros::self& self, std::string url) { - LLCoreHttpUtil::HttpCoroutineAdapter httpAdapter("EventPoller", mHttpPolicy); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EventPoller", mHttpPolicy)); LLSD acknowledge; int errorCount = 0; int counter = mCounter; // saved on the stack for debugging. LL_INFOS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> entering coroutine." << LL_ENDL; + mAdapter = httpAdapter; while (!mDone) { LLSD request; @@ -132,33 +144,35 @@ namespace // LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> request = " // << LLSDXMLStreamer(request) << LL_ENDL; - LL_INFOS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> posting and yielding." << LL_ENDL; - LLSD result = httpAdapter.postAndYield(self, mHttpRequest, url, request); + LL_DEBUGS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> posting and yielding." << LL_ENDL; + LLSD result = httpAdapter->postAndYield(self, mHttpRequest, url, request); // LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = " // << LLSDXMLStreamer(result) << LL_ENDL; - if (mDone) - break; - LLSD httpResults; httpResults = result["http_result"]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); - - if (!httpResults["success"].asBoolean()) + if (!status) { - LL_WARNS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code " - << httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL; - if (httpResults["status"].asInteger() == HTTP_BAD_GATEWAY) + if (status == LLCore::HttpStatus(HTTP_BAD_GATEWAY)) { // A HTTP_BAD_GATEWAY (502) error is our standard timeout response // we get this when there are no events. errorCount = 0; continue; } - - LL_WARNS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> " << LLSDXMLStreamer(result) << (mDone ? " -- done" : "") << LL_ENDL; + + if ((status == LLCore::HttpStatus(LLCore::HttpStatus::LLCORE, LLCore::HE_OP_CANCELED)) || + (status == LLCore::HttpStatus(HTTP_NOT_FOUND))) + { + LL_WARNS() << "Canceling coroutine" << LL_ENDL; + break; + } + LL_WARNS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code " + << status.toTerseString() << ": '" << httpResults["message"] << "'" << LL_ENDL; if (errorCount < MAX_EVENT_POLL_HTTP_ERRORS) { @@ -481,11 +495,13 @@ LLEventPoll::~LLEventPoll() } #endif } +} LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender): mImpl() { - mImpl = boost::unique_ptr(new LLEventPollImpl(sender)); + mImpl = boost::unique_ptr + (new LLEventPolling::Details::LLEventPollImpl(sender)); mImpl->start(poll_url); } -- cgit v1.2.3 From 9965e13e83e30065ba01f936153d9a82326f1685 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 8 Apr 2015 15:54:34 -0700 Subject: Added timeout on failure. --- indra/newview/lleventpoll.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 625bbfae0c..bf07e1b4ab 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -40,6 +40,7 @@ #include "llcoros.h" #include "lleventcoro.h" #include "llcorehttputil.h" +#include "lleventfilter.h" namespace LLEventPolling { @@ -164,8 +165,7 @@ namespace Details errorCount = 0; continue; } - - if ((status == LLCore::HttpStatus(LLCore::HttpStatus::LLCORE, LLCore::HE_OP_CANCELED)) || + else if ((status == LLCore::HttpStatus(LLCore::HttpStatus::LLCORE, LLCore::HE_OP_CANCELED)) || (status == LLCore::HttpStatus(HTTP_NOT_FOUND))) { LL_WARNS() << "Canceling coroutine" << LL_ENDL; @@ -178,16 +178,18 @@ namespace Details { ++errorCount; - // The 'tick' will return TRUE causing the timer to delete this. int waitToRetry = EVENT_POLL_ERROR_RETRY_SECONDS + errorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC; - LL_WARNS() << "Retrying in " << waitToRetry << - " seconds, error count is now " << errorCount << LL_ENDL; - - // *TODO: Wait for a timeout here - // new LLEventPollEventTimer( - // , this); + { + LL_WARNS() << "<" << counter << "> Retrying in " << waitToRetry << + " seconds, error count is now " << errorCount << LL_ENDL; + LLEventTimeout timeout; + timeout.eventAfter(waitToRetry, LLSD()); + waitForEventOn(self, timeout); + } + if (mDone) + break; continue; } else -- cgit v1.2.3 From 6aa2812fad7746d5072c8b16311872666624a33d Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 8 Apr 2015 15:56:25 -0700 Subject: Removed dead code --- indra/newview/lleventpoll.cpp | 245 ------------------------------------------ 1 file changed, 245 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index bf07e1b4ab..5cd99a83b7 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -53,8 +53,6 @@ namespace Details const F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout. const S32 MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules. -#if 1 - class LLEventPollImpl { public: @@ -253,249 +251,6 @@ namespace Details } -#else - class LLEventPollResponder : public LLHTTPClient::Responder - { - LOG_CLASS(LLEventPollResponder); - public: - - static LLHTTPClient::ResponderPtr start(const std::string& pollURL, const LLHost& sender); - void stop(); - - void makeRequest(); - - /* virtual */ void completedRaw(const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer); - - private: - LLEventPollResponder(const std::string& pollURL, const LLHost& sender); - ~LLEventPollResponder(); - - - void handleMessage(const LLSD& content); - - /* virtual */ void httpFailure(); - /* virtual */ void httpSuccess(); - - private: - - bool mDone; - - std::string mPollURL; - std::string mSender; - - LLSD mAcknowledge; - - // these are only here for debugging so we can see which poller is which - static int sCount; - int mCount; - S32 mErrorCount; - }; - - class LLEventPollEventTimer : public LLEventTimer - { - typedef LLPointer EventPollResponderPtr; - - public: - LLEventPollEventTimer(F32 period, EventPollResponderPtr responder) - : LLEventTimer(period), mResponder(responder) - { } - - virtual BOOL tick() - { - mResponder->makeRequest(); - return TRUE; // Causes this instance to be deleted. - } - - private: - - EventPollResponderPtr mResponder; - }; - - //static - LLHTTPClient::ResponderPtr LLEventPollResponder::start( - const std::string& pollURL, const LLHost& sender) - { - LLHTTPClient::ResponderPtr result = new LLEventPollResponder(pollURL, sender); - LL_INFOS() << "LLEventPollResponder::start <" << sCount << "> " - << pollURL << LL_ENDL; - return result; - } - - void LLEventPollResponder::stop() - { - LL_INFOS() << "LLEventPollResponder::stop <" << mCount << "> " - << mPollURL << LL_ENDL; - // there should be a way to stop a LLHTTPClient request in progress - mDone = true; - } - - int LLEventPollResponder::sCount = 0; - - LLEventPollResponder::LLEventPollResponder(const std::string& pollURL, const LLHost& sender) - : mDone(false), - mPollURL(pollURL), - mCount(++sCount), - mErrorCount(0) - { - //extract host and port of simulator to set as sender - LLViewerRegion *regionp = gAgent.getRegion(); - if (!regionp) - { - LL_ERRS() << "LLEventPoll initialized before region is added." << LL_ENDL; - } - mSender = sender.getIPandPort(); - LL_INFOS() << "LLEventPoll initialized with sender " << mSender << LL_ENDL; - makeRequest(); - } - - LLEventPollResponder::~LLEventPollResponder() - { - stop(); - LL_DEBUGS() << "LLEventPollResponder::~Impl <" << mCount << "> " - << mPollURL << LL_ENDL; - } - - // virtual - void LLEventPollResponder::completedRaw(const LLChannelDescriptors& channels, - const LLIOPipe::buffer_ptr_t& buffer) - { - if (getStatus() == HTTP_BAD_GATEWAY) - { - // These errors are not parsable as LLSD, - // which LLHTTPClient::Responder::completedRaw will try to do. - httpCompleted(); - } - else - { - LLHTTPClient::Responder::completedRaw(channels,buffer); - } - } - - void LLEventPollResponder::makeRequest() - { - LLSD request; - request["ack"] = mAcknowledge; - request["done"] = mDone; - - LL_DEBUGS() << "LLEventPollResponder::makeRequest <" << mCount << "> ack = " - << LLSDXMLStreamer(mAcknowledge) << LL_ENDL; - LLHTTPClient::post(mPollURL, request, this); - } - - void LLEventPollResponder::handleMessage(const LLSD& content) - { - std::string msg_name = content["message"]; - LLSD message; - message["sender"] = mSender; - message["body"] = content["body"]; - LLMessageSystem::dispatch(msg_name, message); - } - - //virtual - void LLEventPollResponder::httpFailure() - { - if (mDone) return; - - // A HTTP_BAD_GATEWAY (502) error is our standard timeout response - // we get this when there are no events. - if ( getStatus() == HTTP_BAD_GATEWAY ) - { - mErrorCount = 0; - makeRequest(); - } - else if (mErrorCount < MAX_EVENT_POLL_HTTP_ERRORS) - { - ++mErrorCount; - - // The 'tick' will return TRUE causing the timer to delete this. - new LLEventPollEventTimer(EVENT_POLL_ERROR_RETRY_SECONDS - + mErrorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC - , this); - - LL_WARNS() << dumpResponse() << LL_ENDL; - } - else - { - LL_WARNS() << dumpResponse() - << " [count:" << mCount << "] " - << (mDone ? " -- done" : "") << LL_ENDL; - stop(); - - // At this point we have given up and the viewer will not receive HTTP messages from the simulator. - // IMs, teleports, about land, selecing 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. - - // *NOTE:Mani - The following condition check to see if this failing event poll - // is attached to the Agent's main region. If so we disconnect the viewer. - // Else... its a child region and we just leave the dead event poll stopped and - // continue running. - if(gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSender) - { - LL_WARNS() << "Forcing disconnect due to stalled main region event poll." << LL_ENDL; - LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection")); - } - } - } - - //virtual - void LLEventPollResponder::httpSuccess() - { - LL_DEBUGS() << "LLEventPollResponder::result <" << mCount << ">" - << (mDone ? " -- done" : "") << LL_ENDL; - - if (mDone) return; - - mErrorCount = 0; - - const LLSD& content = getContent(); - if (!content.isMap() || - !content.get("events") || - !content.get("id")) - { - LL_WARNS() << "received event poll with no events or id key: " << dumpResponse() << LL_ENDL; - makeRequest(); - return; - } - - mAcknowledge = content["id"]; - LLSD events = content["events"]; - - if(mAcknowledge.isUndefined()) - { - LL_WARNS() << "LLEventPollResponder: 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() << "LLEventPollResponder::httpSuccess <" << mCount << "> " << events.size() << "events (id " - << LLSDXMLStreamer(mAcknowledge) << ")" << LL_ENDL; - - LLSD::array_const_iterator i = events.beginArray(); - LLSD::array_const_iterator end = events.endArray(); - for (; i != end; ++i) - { - if (i->has("message")) - { - handleMessage(*i); - } - } - - makeRequest(); - } -} - -LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender) - : mImpl(LLEventPollResponder::start(poll_url, sender)) -{ } - -LLEventPoll::~LLEventPoll() -{ - LLHTTPClient::Responder* responderp = mImpl.get(); - LLEventPollResponder* event_poll_responder = dynamic_cast(responderp); - if (event_poll_responder) event_poll_responder->stop(); -} -#endif } } -- cgit v1.2.3 From fb082a185d9988a5ced8b92c9d2a89e24739cbcf Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 8 Apr 2015 17:25:01 -0700 Subject: Couple of cleanup items. Switch to Long poll HTTP policy for event polling. --- indra/newview/lleventpoll.cpp | 62 ++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 5cd99a83b7..a35140a6a7 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -46,12 +46,6 @@ namespace LLEventPolling { 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. - const F32 EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout. - const F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout. - const S32 MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules. class LLEventPollImpl { @@ -60,7 +54,15 @@ namespace Details void start(const std::string &url); void stop(); + private: + // 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; + void eventPollCoro(LLCoros::self& self, std::string url); void handleMessage(const LLSD &content); @@ -76,6 +78,10 @@ namespace Details }; + const F32 LLEventPollImpl::EVENT_POLL_ERROR_RETRY_SECONDS = 15.f; // ~ half of a normal timeout. + const F32 LLEventPollImpl::EVENT_POLL_ERROR_RETRY_SECONDS_INC = 5.f; // ~ half of a normal timeout. + const S32 LLEventPollImpl::MAX_EVENT_POLL_HTTP_ERRORS = 10; // ~5 minutes, by the above rules. + int LLEventPollImpl::sNextCounter = 1; @@ -87,7 +93,10 @@ namespace Details mCounter(sNextCounter++) { + LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); + mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest); + mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_LONG_POLL); mSenderIp = sender.getIPandPort(); } @@ -105,9 +114,9 @@ namespace Details if (!url.empty()) { std::string coroname = - LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro", + LLCoros::instance().launch("LLEventPollImpl::eventPollCoro", boost::bind(&LLEventPollImpl::eventPollCoro, this, _1, url)); - LL_INFOS() << coroname << " with url '" << url << LL_ENDL; + LL_INFOS("LLEventPollImpl") << coroname << " with url '" << url << LL_ENDL; } } @@ -131,7 +140,7 @@ namespace Details int errorCount = 0; int counter = mCounter; // saved on the stack for debugging. - LL_INFOS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> entering coroutine." << LL_ENDL; + LL_INFOS("LLEventPollImpl") << " <" << counter << "> entering coroutine." << LL_ENDL; mAdapter = httpAdapter; while (!mDone) @@ -140,14 +149,14 @@ namespace Details request["ack"] = acknowledge; request["done"] = mDone; -// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> request = " -// << LLSDXMLStreamer(request) << LL_ENDL; +// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> request = " +// << LLSDXMLStreamer(request) << LL_ENDL; - LL_DEBUGS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> posting and yielding." << LL_ENDL; + LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> posting and yielding." << LL_ENDL; LLSD result = httpAdapter->postAndYield(self, mHttpRequest, url, request); -// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = " -// << LLSDXMLStreamer(result) << LL_ENDL; +// LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = " +// << LLSDXMLStreamer(result) << LL_ENDL; LLSD httpResults; httpResults = result["http_result"]; @@ -169,25 +178,28 @@ namespace Details LL_WARNS() << "Canceling coroutine" << LL_ENDL; break; } - LL_WARNS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code " + LL_WARNS("LLEventPollImpl") << "<" << counter << "> Error result from LLCoreHttpUtil::HttpCoroHandler. Code " << status.toTerseString() << ": '" << httpResults["message"] << "'" << LL_ENDL; if (errorCount < MAX_EVENT_POLL_HTTP_ERRORS) { ++errorCount; - int waitToRetry = EVENT_POLL_ERROR_RETRY_SECONDS + F32 waitToRetry = EVENT_POLL_ERROR_RETRY_SECONDS + errorCount * EVENT_POLL_ERROR_RETRY_SECONDS_INC; + LL_WARNS("LLEventPollImpl") << "<" << counter << "> Retrying in " << waitToRetry << + " seconds, error count is now " << errorCount << LL_ENDL; + { - LL_WARNS() << "<" << counter << "> Retrying in " << waitToRetry << - " seconds, error count is now " << errorCount << LL_ENDL; LLEventTimeout timeout; timeout.eventAfter(waitToRetry, LLSD()); waitForEventOn(self, timeout); } if (mDone) break; + LL_INFOS("LLEventPollImpl") << "<" << counter << "> About to retry request." << LL_ENDL; + continue; } else @@ -205,23 +217,20 @@ namespace Details // continue running. if (gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSenderIp) { - LL_WARNS("LLEventPollImpl::eventPollCoro") << "< " << counter << "> Forcing disconnect due to stalled main region event poll." << LL_ENDL; + LL_WARNS("LLEventPollImpl") << "< " << counter << "> Forcing disconnect due to stalled main region event poll." << LL_ENDL; LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection")); } break; } } - LL_DEBUGS("LLEventPollImpl::eventPollCoro") << " <" << counter << ">" - << (mDone ? " -- done" : "") << LL_ENDL; - errorCount = 0; if (!result.isMap() || !result.get("events") || !result.get("id")) { - LL_WARNS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> received event poll with no events or id key: " << LLSDXMLStreamer(result) << LL_ENDL; + LL_WARNS("LLEventPollImpl") << " <" << counter << "> received event poll with no events or id key: " << LLSDXMLStreamer(result) << LL_ENDL; continue; } @@ -230,12 +239,11 @@ namespace Details if (acknowledge.isUndefined()) { - LL_WARNS("LLEventPollImpl::eventPollCoro") << " id undefined" << LL_ENDL; + LL_WARNS("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() << "LLEventPollResponder::httpSuccess <" << counter << "> " << events.size() << "events (id " - << LLSDXMLStreamer(acknowledge) << ")" << LL_ENDL; + LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> " << events.size() << "events (id " << LLSDXMLStreamer(acknowledge) << ")" << LL_ENDL; LLSD::array_const_iterator i = events.beginArray(); LLSD::array_const_iterator end = events.endArray(); @@ -247,7 +255,7 @@ namespace Details } } } - LL_INFOS("LLEventPollImpl::eventPollCoro") << " <" << counter << "> Leaving coroutine." << LL_ENDL; + LL_INFOS("LLEventPollImpl") << " <" << counter << "> Leaving coroutine." << LL_ENDL; } -- cgit v1.2.3 From e28a5b6eadd4c38498665b44f1c7e197615139f2 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 9 Apr 2015 16:46:41 -0700 Subject: 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. --- indra/newview/lleventpoll.cpp | 47 +++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 24 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index a35140a6a7..25504e7cbf 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -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; - } } -- cgit v1.2.3 From 794cdbc2ae2d7078a7af5319e84667f0d6b15297 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 9 Apr 2015 17:14:39 -0700 Subject: Issue with LL_WARNS_IF sort out later. --- indra/newview/lleventpoll.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 25504e7cbf..d731428464 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -240,7 +240,10 @@ namespace Details acknowledge = result["id"]; LLSD events = result["events"]; - LL_WARNS_IF((acknowledge.isUndefined()), "LLEventPollImpl") << " id undefined" << LL_ENDL; + if (acknowledge.isUndefined()) + { + LL_WARNS("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; -- cgit v1.2.3 From 3e004ce66e1fa07421c138a20eb0dba61c5b26b3 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Mon, 11 May 2015 16:52:02 -0700 Subject: Updated feature manager downloader to coroutine. Added "raw" coroutine handler (returns raw result as LLSD::Binary) and split out the guts of the get, put, etc methods. Moved getStatusFromLLSD from HttpCoroHandler into HttpCorutineAdapter --- indra/newview/lleventpoll.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index d731428464..9ba3e7ef5b 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -162,7 +162,7 @@ namespace Details // << LLSDXMLStreamer(result) << LL_ENDL; LLSD httpResults = result["http_result"]; - LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroHandler::getStatusFromLLSD(httpResults); + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); if (!status) { -- cgit v1.2.3 From 0d3fb07bfa205b65f242ef2b761e827ff30e42fe Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 3 Jun 2015 16:04:40 -0700 Subject: Remove vestigial httpclient.h include from files that no longer need it. --- indra/newview/lleventpoll.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 9ba3e7ef5b..03a380f2f6 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -30,8 +30,6 @@ #include "llappviewer.h" #include "llagent.h" -#include "llhttpclient.h" -#include "llhttpconstants.h" #include "llsdserialize.h" #include "lleventtimer.h" #include "llviewerregion.h" -- cgit v1.2.3 From b262ded7e0cf21314524bf702b0e4fe28a3c3060 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 1 Jul 2015 18:33:29 -0400 Subject: MAINT-5351: Remove 'self' parameter from coroutine functions. lleventcoro_test.cpp runs clean (as modified for new API), and all the rest builds clean, but the resulting viewer is as yet untested. --- indra/newview/lleventpoll.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 03a380f2f6..54da226209 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -61,7 +61,7 @@ namespace Details 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(std::string url); void handleMessage(const LLSD &content); @@ -113,7 +113,7 @@ namespace Details { std::string coroname = LLCoros::instance().launch("LLEventPollImpl::eventPollCoro", - boost::bind(&LLEventPollImpl::eventPollCoro, this, _1, url)); + boost::bind(&LLEventPollImpl::eventPollCoro, this, url)); LL_INFOS("LLEventPollImpl") << coroname << " with url '" << url << LL_ENDL; } } @@ -131,7 +131,7 @@ namespace Details } } - void LLEventPollImpl::eventPollCoro(LLCoros::self& self, std::string url) + void LLEventPollImpl::eventPollCoro(std::string url) { LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EventPoller", mHttpPolicy)); LLSD acknowledge; @@ -154,7 +154,7 @@ namespace Details // << LLSDXMLStreamer(request) << LL_ENDL; LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> posting and yielding." << LL_ENDL; - LLSD result = httpAdapter->postAndYield(self, mHttpRequest, url, request); + LLSD result = httpAdapter->postAndYield(mHttpRequest, url, request); // LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = " // << LLSDXMLStreamer(result) << LL_ENDL; @@ -197,7 +197,7 @@ namespace Details " seconds, error count is now " << errorCount << LL_ENDL; timeout.eventAfter(waitToRetry, LLSD()); - waitForEventOn(self, timeout); + waitForEventOn(timeout); if (mDone) break; -- cgit v1.2.3 From 247eb0c9c3418c10be8f2a0e3c8116758efa702f Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 7 Jul 2015 19:41:27 +0100 Subject: Backout selfles merge 738255dbbfd679d9e615baab3398e5e345bbb3c5 --- indra/newview/lleventpoll.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 54da226209..03a380f2f6 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -61,7 +61,7 @@ namespace Details static const F32 EVENT_POLL_ERROR_RETRY_SECONDS_INC; static const S32 MAX_EVENT_POLL_HTTP_ERRORS; - void eventPollCoro(std::string url); + void eventPollCoro(LLCoros::self& self, std::string url); void handleMessage(const LLSD &content); @@ -113,7 +113,7 @@ namespace Details { std::string coroname = LLCoros::instance().launch("LLEventPollImpl::eventPollCoro", - boost::bind(&LLEventPollImpl::eventPollCoro, this, url)); + boost::bind(&LLEventPollImpl::eventPollCoro, this, _1, url)); LL_INFOS("LLEventPollImpl") << coroname << " with url '" << url << LL_ENDL; } } @@ -131,7 +131,7 @@ namespace Details } } - void LLEventPollImpl::eventPollCoro(std::string url) + void LLEventPollImpl::eventPollCoro(LLCoros::self& self, std::string url) { LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EventPoller", mHttpPolicy)); LLSD acknowledge; @@ -154,7 +154,7 @@ namespace Details // << LLSDXMLStreamer(request) << LL_ENDL; LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> posting and yielding." << LL_ENDL; - LLSD result = httpAdapter->postAndYield(mHttpRequest, url, request); + LLSD result = httpAdapter->postAndYield(self, mHttpRequest, url, request); // LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = " // << LLSDXMLStreamer(result) << LL_ENDL; @@ -197,7 +197,7 @@ namespace Details " seconds, error count is now " << errorCount << LL_ENDL; timeout.eventAfter(waitToRetry, LLSD()); - waitForEventOn(timeout); + waitForEventOn(self, timeout); if (mDone) break; -- cgit v1.2.3 From efa9a0f99c17b2b937120bcad6e3d45944122ed9 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Fri, 10 Jul 2015 19:30:10 -0400 Subject: Backed out changeset bab1000e1b2d: restore 'selfless' changes --- indra/newview/lleventpoll.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 03a380f2f6..54da226209 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -61,7 +61,7 @@ namespace Details 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(std::string url); void handleMessage(const LLSD &content); @@ -113,7 +113,7 @@ namespace Details { std::string coroname = LLCoros::instance().launch("LLEventPollImpl::eventPollCoro", - boost::bind(&LLEventPollImpl::eventPollCoro, this, _1, url)); + boost::bind(&LLEventPollImpl::eventPollCoro, this, url)); LL_INFOS("LLEventPollImpl") << coroname << " with url '" << url << LL_ENDL; } } @@ -131,7 +131,7 @@ namespace Details } } - void LLEventPollImpl::eventPollCoro(LLCoros::self& self, std::string url) + void LLEventPollImpl::eventPollCoro(std::string url) { LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("EventPoller", mHttpPolicy)); LLSD acknowledge; @@ -154,7 +154,7 @@ namespace Details // << LLSDXMLStreamer(request) << LL_ENDL; LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> posting and yielding." << LL_ENDL; - LLSD result = httpAdapter->postAndYield(self, mHttpRequest, url, request); + LLSD result = httpAdapter->postAndYield(mHttpRequest, url, request); // LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = " // << LLSDXMLStreamer(result) << LL_ENDL; @@ -197,7 +197,7 @@ namespace Details " seconds, error count is now " << errorCount << LL_ENDL; timeout.eventAfter(waitToRetry, LLSD()); - waitForEventOn(self, timeout); + waitForEventOn(timeout); if (mDone) break; -- cgit v1.2.3 From f1be78f7e235bfe9395eed748154d77763d5ea65 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Sat, 11 Jul 2015 08:06:15 -0400 Subject: MAINT-5351: Finish messy merge restoring 'selfless' changes. --- indra/newview/lleventpoll.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 54da226209..0aad1d5ba9 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -197,7 +197,7 @@ namespace Details " seconds, error count is now " << errorCount << LL_ENDL; timeout.eventAfter(waitToRetry, LLSD()); - waitForEventOn(timeout); + llcoro::waitForEventOn(timeout); if (mDone) break; -- cgit v1.2.3 From 75c6549fde060e974c90636685962ee373f94202 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Fri, 18 Sep 2015 11:39:22 -0700 Subject: Set consistent terminology for yield/wait -> suspend for coroutines. --- indra/newview/lleventpoll.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/lleventpoll.cpp') diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp index 0aad1d5ba9..021d17251d 100755 --- a/indra/newview/lleventpoll.cpp +++ b/indra/newview/lleventpoll.cpp @@ -127,7 +127,7 @@ namespace Details if (adapter) { // cancel the yielding operation if any. - adapter->cancelYieldingOperation(); + adapter->cancelSuspendedOperation(); } } @@ -154,7 +154,7 @@ namespace Details // << LLSDXMLStreamer(request) << LL_ENDL; LL_DEBUGS("LLEventPollImpl") << " <" << counter << "> posting and yielding." << LL_ENDL; - LLSD result = httpAdapter->postAndYield(mHttpRequest, url, request); + LLSD result = httpAdapter->postAndSuspend(mHttpRequest, url, request); // LL_DEBUGS("LLEventPollImpl::eventPollCoro") << "<" << counter << "> result = " // << LLSDXMLStreamer(result) << LL_ENDL; @@ -197,7 +197,7 @@ namespace Details " seconds, error count is now " << errorCount << LL_ENDL; timeout.eventAfter(waitToRetry, LLSD()); - llcoro::waitForEventOn(timeout); + llcoro::suspendUntilEventOn(timeout); if (mDone) break; -- cgit v1.2.3