diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index e76ba4aa93..7e7a1a004f 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -13563,5 +13563,27 @@ Change of this parameter will affect the layout of buttons in notification toast Value 1 + ImagePipelineUseHTTPFetchMaxRequests + + Comment + Max number of simultaneous textures to request when using HTTP texture fetch. Changing this setting above 8 will most likely cause texture loading problems, setting above 32 *WILL* cause loading failures. + Persist + 1 + Type + S32 + Value + 8 + + ImagePipelineHTTPMaxFailCountFallback + + Comment + Maximum failures during HTTP GET texture fetch per region before fallback to UDP fetch occurs. + Persist + 1 + Type + U32 + Value + 25 + diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 18c3a3b87d..a0e24a2ccd 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1018,7 +1018,7 @@ bool LLTextureFetchWorker::doWork(S32 param) else region = LLWorld::getInstance()->getRegion(mHost); - if (region) + if (region && !LLAppViewer::getTextureFetch()->isHttpFailLimitReached()) { std::string http_url = region->getHttpUrl() ; if (!http_url.empty()) @@ -1134,14 +1134,15 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == SEND_HTTP_REQ) { - if(mCanUseHTTP) + if(mCanUseHTTP && !LLAppViewer::getTextureFetch()->isHttpFailLimitReached()) { //NOTE: //control the number of the http requests issued for: //1, not openning too many file descriptors at the same time; //2, control the traffic of http so udp gets bandwidth. // - static const S32 MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE = 8 ; + //static const S32 MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE = 8 ; + static LLCachedControl MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE(gSavedSettings, "ImagePipelineUseHTTPFetchMaxRequests"); if(mFetcher->getNumHTTPRequests() > MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE) { return false ; //wait. @@ -1213,7 +1214,15 @@ bool LLTextureFetchWorker::doWork(S32 param) } else //can not use http fetch. { - return true ; //abort + // Ansariel: roll back to try UDP + if(mCanUseNET) + { + mState = INIT ; + mCanUseHTTP = false ; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + return false ; + } + else return true ; //abort } } @@ -1245,7 +1254,13 @@ bool LLTextureFetchWorker::doWork(S32 param) // for a short time (~1s) to ease server load? Ideally the server would queue // requests instead of returning 503... we already limit the number pending. ++mHTTPFailCount; - max_attempts = mHTTPFailCount+1; // Keep retrying + + // Ansariel: Just increase the normal counter. We're gonna fallback to UDP + // if problem continues. + //max_attempts = mHTTPFailCount+1; // Keep retrying + const S32 HTTP_MAX_RETRY_COUNT = 3; + max_attempts = HTTP_MAX_RETRY_COUNT + 1; + LLAppViewer::getTextureFetch()->addHttpFailCount(); LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL; } else @@ -1253,6 +1268,7 @@ bool LLTextureFetchWorker::doWork(S32 param) const S32 HTTP_MAX_RETRY_COUNT = 3; max_attempts = HTTP_MAX_RETRY_COUNT + 1; ++mHTTPFailCount; + LLAppViewer::getTextureFetch()->addHttpFailCount(); llinfos << "HTTP GET failed for: " << mUrl << " Status: " << mGetStatus << " Reason: '" << mGetReason << "'" << " Attempt:" << mHTTPFailCount+1 << "/" << max_attempts << llendl; @@ -1269,9 +1285,22 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { - resetFormattedData(); - mState = DONE; - return true; // failed + // Ansariel: What's this? On any other HTTP failure except + // not found we simply give up? No way! Let's + // try UDP as fallback! + if (mCanUseNET) + { + mState = INIT; + mCanUseHTTP = false; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + return false; + } + else + { + resetFormattedData(); + mState = DONE; + return true; // failed + } } } else @@ -1824,11 +1853,14 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHTTPTextureBits(0), mTotalHTTPRequests(0), mCurlGetRequest(NULL), - mQAMode(qa_mode) + mQAMode(qa_mode), + mTotalHttpFailCount(0), + mHttpFailMutex(NULL) { mCurlPOSTRequestCount = 0; mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS"); mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold")); + mMaxHttpFailCountBeforeFallback = gSavedSettings.getU32("ImagePipelineHTTPMaxFailCountFallback"); } LLTextureFetch::~LLTextureFetch() @@ -1894,7 +1926,6 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con desired_size = TEXTURE_CACHE_ENTRY_SIZE; desired_discard = MAX_DISCARD_LEVEL; } - if (worker) { @@ -2803,6 +2834,30 @@ void LLTextureFetch::cmdDoWork() } } +void LLTextureFetch::addHttpFailCount() +{ + LLMutexLock lock(&mHttpFailMutex); + ++mTotalHttpFailCount; + llwarns << "Increasing HTTP GET fail count to: " << mTotalHttpFailCount << llendl; +} + +void LLTextureFetch::processRegionChanged() +{ + llinfos << "Region changed. Resetting HTTP GET failure counter." << llendl; + LLMutexLock lock(&mHttpFailMutex); + mTotalHttpFailCount = 0; +} + +void LLTextureFetch::setMaxHttpFailCountBeforeFallback(U32 maxFailCount) +{ + llinfos << "Setting max failure count before fallback for HTTP GET to " << maxFailCount << llendl; + mMaxHttpFailCountBeforeFallback = maxFailCount; +} + +bool LLTextureFetch::isHttpFailLimitReached() +{ + return mTotalHttpFailCount >= mMaxHttpFailCountBeforeFallback; +} ////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index d101da1f4b..4d22e7eb6c 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -106,6 +106,11 @@ public: inline void incrCurlPOSTCount() { mCurlPOSTRequestCount++; } inline void decrCurlPOSTCount() { mCurlPOSTRequestCount--; } + void addHttpFailCount(); + bool isHttpFailLimitReached(); + void processRegionChanged(); + void setMaxHttpFailCountBeforeFallback(U32 maxFailCount); + protected: void addToNetworkQueue(LLTextureFetchWorker* worker); void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); @@ -161,6 +166,11 @@ public: S32 mBadPacketCount; private: + LLMutex mHttpFailMutex; + U32 mTotalHttpFailCount; + U32 mMaxHttpFailCountBeforeFallback; + + LLMutex mQueueMutex; //to protect mRequestMap and mCommands only LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue. diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 7266429f84..81d3cc34e9 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -73,6 +73,7 @@ #include "llcombobox.h" #include "llstatusbar.h" #include "llupdaterservice.h" +#include "lltexturefetch.h" #ifdef TOGGLE_HACKED_GODLIKE_VIEWER BOOL gHackGodmode = FALSE; @@ -549,6 +550,12 @@ void toggle_updater_service_active(LLControlVariable* control, const LLSD& new_v } } +static bool handleImagePipelineHTTPMaxFailCountFallback(const LLSD& newvalue) +{ + LLAppViewer::getTextureFetch()->setMaxHttpFailCountBeforeFallback(newvalue.asInteger()); + return true; +} + //////////////////////////////////////////////////////////////////////////// void settings_setup_listeners() @@ -704,6 +711,7 @@ void settings_setup_listeners() gSavedSettings.getControl("UpdaterServiceSetting")->getSignal()->connect(&toggle_updater_service_active); gSavedSettings.getControl("ForceShowGrid")->getSignal()->connect(boost::bind(&handleForceShowGrid, _2)); gSavedSettings.getControl("RenderTransparentWater")->getSignal()->connect(boost::bind(&handleRenderTransparentWaterChanged, _2)); + gSavedSettings.getControl("ImagePipelineHTTPMaxFailCountFallback")->getSignal()->connect(boost::bind(&handleImagePipelineHTTPMaxFailCountFallback, _2)); } #if TEST_CACHED_CONTROL diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 3b5d96aa59..32f3af1b06 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -119,6 +119,8 @@ #include "llnotificationmanager.h" // +#include "lltexturefetch.h" + #if LL_MSVC // disable boost::lexical_cast warning #pragma warning (disable:4702) @@ -4021,6 +4023,9 @@ void process_teleport_finish(LLMessageSystem* msg, void**) // Viewer trusts the simulator. gMessageSystem->enableCircuit(sim_host, TRUE); LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); + + // Ansariel: New region -> reset fail counter for texture fetcher + LLAppViewer::getTextureFetch()->processRegionChanged(); /* // send camera update to new region @@ -4299,6 +4304,9 @@ void process_crossed_region(LLMessageSystem* msg, void**) LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); regionp->setSeedCapability(seedCap); + + // Ansariel: New region -> reset fail counter for texture fetcher + LLAppViewer::getTextureFetch()->processRegionChanged(); }