summaryrefslogtreecommitdiff
path: root/indra/newview/lltexturefetch.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/lltexturefetch.cpp')
-rwxr-xr-xindra/newview/lltexturefetch.cpp154
1 files changed, 106 insertions, 48 deletions
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index d9a874be49..a64a6ee091 100755
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -241,8 +241,10 @@ LLTrace::EventStatHandle<F64Milliseconds > LLTextureFetch::sCacheReadLatency("te
// Tuning/Parameterization Constants
-static const S32 HTTP_REQUESTS_IN_QUEUE_HIGH_WATER = 40; // Maximum requests to have active in HTTP
-static const S32 HTTP_REQUESTS_IN_QUEUE_LOW_WATER = 20; // Active level at which to refill
+static const S32 HTTP_PIPE_REQUESTS_HIGH_WATER = 100; // Maximum requests to have active in HTTP (pipelined)
+static const S32 HTTP_PIPE_REQUESTS_LOW_WATER = 50; // Active level at which to refill
+static const S32 HTTP_NONPIPE_REQUESTS_HIGH_WATER = 40;
+static const S32 HTTP_NONPIPE_REQUESTS_LOW_WATER = 20;
// BUG-3323/SH-4375
// *NOTE: This is a heuristic value. Texture fetches have a habit of using a
@@ -481,12 +483,12 @@ private:
bool acquireHttpSemaphore()
{
llassert(! mHttpHasResource);
- if (mFetcher->mHttpSemaphore <= 0)
+ if (mFetcher->mHttpSemaphore >= mFetcher->mHttpHighWater)
{
return false;
}
mHttpHasResource = true;
- mFetcher->mHttpSemaphore--;
+ mFetcher->mHttpSemaphore++;
return true;
}
@@ -496,7 +498,8 @@ private:
{
llassert(mHttpHasResource);
mHttpHasResource = false;
- mFetcher->mHttpSemaphore++;
+ mFetcher->mHttpSemaphore--;
+ llassert_always(mFetcher->mHttpSemaphore >= 0);
}
private:
@@ -608,16 +611,16 @@ private:
LLCore::HttpHandle mHttpHandle; // Handle of any active request
LLCore::BufferArray * mHttpBufferArray; // Refcounted pointer to response data
- S32 mHttpPolicyClass;
+ S32 mHttpPolicyClass;
bool mHttpActive; // Active request to http library
- U32 mHttpReplySize, // Actual received data size
- mHttpReplyOffset; // Actual received data offset
+ U32 mHttpReplySize, // Actual received data size
+ mHttpReplyOffset; // Actual received data offset
bool mHttpHasResource; // Counts against Fetcher's mHttpSemaphore
// State history
- U32 mCacheReadCount,
- mCacheWriteCount,
- mResourceWaitCount; // Requests entering WAIT_HTTP_RESOURCE2
+ U32 mCacheReadCount,
+ mCacheWriteCount,
+ mResourceWaitCount; // Requests entering WAIT_HTTP_RESOURCE2
};
//////////////////////////////////////////////////////////////////////////////
@@ -1325,7 +1328,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
}
- static LLCachedControl<bool> use_http(gSavedSettings,"ImagePipelineUseHTTP", true);
+ static LLCachedControl<bool> use_http(gSavedSettings, "ImagePipelineUseHTTP", true);
// if (mHost != LLHost::invalid) get_url = false;
if ( use_http && mCanUseHTTP && mUrl.empty())//get http url.
@@ -1473,6 +1476,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == SEND_HTTP_REQ)
{
+ // Also used in llmeshrepository
+ static LLCachedControl<bool> disable_range_req(gSavedSettings, "HttpRangeRequestsDisable", false);
+
if (! mCanUseHTTP)
{
releaseHttpSemaphore();
@@ -1528,22 +1534,47 @@ bool LLTextureFetchWorker::doWork(S32 param)
mRequestedOffset -= 1;
mRequestedSize += 1;
}
-
mHttpHandle = LLCORE_HTTP_HANDLE_INVALID;
- if (!mUrl.empty())
- {
- mRequestedTimer.reset();
- mLoaded = FALSE;
- mGetStatus = LLCore::HttpStatus();
- mGetReason.clear();
- LL_DEBUGS(LOG_TXT) << "HTTP GET: " << mID << " Offset: " << mRequestedOffset
- << " Bytes: " << mRequestedSize
- << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << mFetcher->mMaxBandwidth
- << LL_ENDL;
- // Will call callbackHttpGet when curl request completes
- // Only server bake images use the returned headers currently, for getting retry-after field.
- LLCore::HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions;
+ if (mUrl.empty())
+ {
+ // *FIXME: This should not be reachable except it has become
+ // so after some recent 'work'. Need to track this down
+ // and illuminate the unenlightened.
+ LL_WARNS(LOG_TXT) << "HTTP GET request failed for " << mID
+ << " on empty URL." << LL_ENDL;
+ resetFormattedData();
+ releaseHttpSemaphore();
+ return true; // failed
+ }
+
+ mRequestedTimer.reset();
+ mLoaded = FALSE;
+ mGetStatus = LLCore::HttpStatus();
+ mGetReason.clear();
+ LL_DEBUGS(LOG_TXT) << "HTTP GET: " << mID << " Offset: " << mRequestedOffset
+ << " Bytes: " << mRequestedSize
+ << " Bandwidth(kbps): " << mFetcher->getTextureBandwidth() << "/" << mFetcher->mMaxBandwidth
+ << LL_ENDL;
+
+ // Will call callbackHttpGet when curl request completes
+ // Only server bake images use the returned headers currently, for getting retry-after field.
+ LLCore::HttpOptions *options = (mFTType == FTT_SERVER_BAKE) ? mFetcher->mHttpOptionsWithHeaders: mFetcher->mHttpOptions;
+ if (disable_range_req)
+ {
+ // 'Range:' requests may be disabled in which case all HTTP
+ // texture fetches result in full fetches. This can be used
+ // by people with questionable ISPs or networking gear that
+ // doesn't handle these well.
+ mHttpHandle = mFetcher->mHttpRequest->requestGet(mHttpPolicyClass,
+ mWorkPriority,
+ mUrl,
+ options,
+ mFetcher->mHttpHeaders,
+ this);
+ }
+ else
+ {
mHttpHandle = mFetcher->mHttpRequest->requestGetByteRange(mHttpPolicyClass,
mWorkPriority,
mUrl,
@@ -1557,7 +1588,11 @@ bool LLTextureFetchWorker::doWork(S32 param)
}
if (LLCORE_HTTP_HANDLE_INVALID == mHttpHandle)
{
- LL_WARNS(LOG_TXT) << "HTTP GET request failed for " << mID << LL_ENDL;
+ LLCore::HttpStatus status(mFetcher->mHttpRequest->getStatus());
+ LL_WARNS(LOG_TXT) << "HTTP GET request failed for " << mID
+ << ", Status: " << status.toTerseString()
+ << " Reason: '" << status.toString() << "'"
+ << LL_ENDL;
resetFormattedData();
releaseHttpSemaphore();
return true; // failed
@@ -1613,10 +1648,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
else if (http_service_unavail == mGetStatus)
{
LL_INFOS_ONCE(LOG_TXT) << "Texture server busy (503): " << mUrl << LL_ENDL;
- LL_INFOS(LOG_TXT) << "503: HTTP GET failed for: " << mUrl
- << " Status: " << mGetStatus.toHex()
- << " Reason: '" << mGetReason << "'"
- << LL_ENDL;
}
else if (http_not_sat == mGetStatus)
{
@@ -1774,7 +1805,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == DECODE_IMAGE)
{
- static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled", false);
+ static LLCachedControl<bool> textures_decode_disabled(gSavedSettings, "TextureDecodeDisabled", false);
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
if (textures_decode_disabled)
@@ -2485,7 +2516,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mHttpHeaders(NULL),
mHttpMetricsHeaders(NULL),
mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
- mHttpSemaphore(HTTP_REQUESTS_IN_QUEUE_HIGH_WATER),
mTotalCacheReadCount(0U),
mTotalCacheWriteCount(0U),
mTotalResourceWaitCount(0U),
@@ -2497,6 +2527,22 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mMaxBandwidth = gSavedSettings.getF32("ThrottleBandwidthKBPS");
mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), U32Bytes(gSavedSettings.getU32("TextureLoggingThreshold")));
+ LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp());
+ mHttpPolicyClass = app_core_http.getPolicy(LLAppCoreHttp::AP_TEXTURE);
+ mHttpRequest = new LLCore::HttpRequest;
+ mHttpOptions = new LLCore::HttpOptions;
+ mHttpOptionsWithHeaders = new LLCore::HttpOptions;
+ mHttpOptionsWithHeaders->setWantHeaders(true);
+ mHttpHeaders = new LLCore::HttpHeaders;
+ mHttpHeaders->append("Accept", "image/x-j2c");
+ mHttpMetricsHeaders = new LLCore::HttpHeaders;
+ mHttpMetricsHeaders->append("Content-Type", "application/llsd+xml");
+ mHttpHighWater = HTTP_NONPIPE_REQUESTS_HIGH_WATER;
+ mHttpLowWater = HTTP_NONPIPE_REQUESTS_LOW_WATER;
+ mHttpSemaphore = 0;
+
+ // Conditionally construct debugger object after 'this' is
+ // fully initialized.
LLTextureFetchDebugger::sDebuggerEnabled = gSavedSettings.getBOOL("TextureFetchDebuggerEnabled");
if(LLTextureFetchDebugger::isEnabled())
{
@@ -2509,16 +2555,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
}
mOriginFetchSource = mFetchSource;
}
-
- mHttpRequest = new LLCore::HttpRequest;
- mHttpOptions = new LLCore::HttpOptions;
- mHttpOptionsWithHeaders = new LLCore::HttpOptions;
- mHttpOptionsWithHeaders->setWantHeaders(true);
- mHttpHeaders = new LLCore::HttpHeaders;
- mHttpHeaders->append("Accept", "image/x-j2c");
- mHttpMetricsHeaders = new LLCore::HttpHeaders;
- mHttpMetricsHeaders->append("Content-Type", "application/llsd+xml");
- mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_TEXTURE);
}
LLTextureFetch::~LLTextureFetch()
@@ -2990,6 +3026,20 @@ bool LLTextureFetch::runCondition()
// Threads: Ttf
void LLTextureFetch::commonUpdate()
{
+ // Update low/high water levels based on pipelining. We pick
+ // up setting eventually, so the semaphore/request level can
+ // fall outside the [0..HIGH_WATER] range. Expect that.
+ if (LLAppViewer::instance()->getAppCoreHttp().isPipelined(LLAppCoreHttp::AP_TEXTURE))
+ {
+ mHttpHighWater = HTTP_PIPE_REQUESTS_HIGH_WATER;
+ mHttpLowWater = HTTP_PIPE_REQUESTS_LOW_WATER;
+ }
+ else
+ {
+ mHttpHighWater = HTTP_NONPIPE_REQUESTS_HIGH_WATER;
+ mHttpLowWater = HTTP_NONPIPE_REQUESTS_LOW_WATER;
+ }
+
// Release waiters
releaseHttpWaiters();
@@ -3651,8 +3701,16 @@ void LLTextureFetch::releaseHttpWaiters()
{
// Use mHttpSemaphore rather than mHTTPTextureQueue.size()
// to avoid a lock.
- if (mHttpSemaphore < (HTTP_REQUESTS_IN_QUEUE_HIGH_WATER - HTTP_REQUESTS_IN_QUEUE_LOW_WATER))
+ if (mHttpSemaphore >= mHttpLowWater)
return;
+ S32 needed(mHttpHighWater - mHttpSemaphore);
+ if (needed <= 0)
+ {
+ // Would only happen if High/LowWater were changed behind
+ // our back. In that case, defer fill until usage falls within
+ // limits.
+ return;
+ }
// Quickly make a copy of all the LLUIDs. Get off the
// mutex as early as possible.
@@ -3701,10 +3759,10 @@ void LLTextureFetch::releaseHttpWaiters()
tids.clear();
// Sort into priority order, if necessary and only as much as needed
- if (tids2.size() > mHttpSemaphore)
+ if (tids2.size() > needed)
{
LLTextureFetchWorker::Compare compare;
- std::partial_sort(tids2.begin(), tids2.begin() + mHttpSemaphore, tids2.end(), compare);
+ std::partial_sort(tids2.begin(), tids2.begin() + needed, tids2.end(), compare);
}
// Release workers up to the high water mark. Since we aren't
@@ -4544,7 +4602,7 @@ S32 LLTextureFetchDebugger::fillCurlQueue()
mNbCurlCompleted = mFetchingHistory.size();
return 0;
}
- if (mNbCurlRequests > HTTP_REQUESTS_IN_QUEUE_LOW_WATER)
+ if (mNbCurlRequests > HTTP_NONPIPE_REQUESTS_LOW_WATER)
{
return mNbCurlRequests;
}
@@ -4577,7 +4635,7 @@ S32 LLTextureFetchDebugger::fillCurlQueue()
mFetchingHistory[i].mHttpHandle = handle;
mFetchingHistory[i].mCurlState = FetchEntry::CURL_IN_PROGRESS;
mNbCurlRequests++;
- if (mNbCurlRequests >= HTTP_REQUESTS_IN_QUEUE_HIGH_WATER) // emulate normal pipeline
+ if (mNbCurlRequests >= HTTP_NONPIPE_REQUESTS_HIGH_WATER) // emulate normal pipeline
{
break;
}