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
+
+ ImagePipelineHTTPMaxFailCountFallback
+
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();
}