Shoddy servers need shoddy workarounds
This commit is contained in:
@@ -365,6 +365,78 @@ private:
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class SGHostBlackList{
|
||||||
|
static const int MAX_ERRORCOUNT = 5;
|
||||||
|
struct BlackListEntry {
|
||||||
|
LLHost host;
|
||||||
|
clock_t timeUntil;
|
||||||
|
U32 reason;
|
||||||
|
int errorCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
static LLMutex* sMutex;
|
||||||
|
typedef std::vector<BlackListEntry> blacklist_t;
|
||||||
|
typedef blacklist_t::iterator iter;
|
||||||
|
static blacklist_t blacklist;
|
||||||
|
|
||||||
|
static bool is_obsolete(BlackListEntry entry) {
|
||||||
|
clock_t now = clock();
|
||||||
|
return (now > entry.timeUntil);
|
||||||
|
} //should make a functor. if i cared.
|
||||||
|
|
||||||
|
static void cleanup() {
|
||||||
|
std::remove_if(blacklist.begin(), blacklist.end(), is_obsolete);
|
||||||
|
}
|
||||||
|
|
||||||
|
static iter find(LLHost& host) {
|
||||||
|
cleanup();
|
||||||
|
for(blacklist_t::iterator i = blacklist.begin(); i != blacklist.end(); ++i) {
|
||||||
|
if (i->host == host) return i;
|
||||||
|
}
|
||||||
|
return blacklist.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lock() {
|
||||||
|
if (!sMutex)
|
||||||
|
sMutex = new LLMutex(0);
|
||||||
|
sMutex->lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void unlock() {
|
||||||
|
sMutex->unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static bool isBlacklisted(LLHost& host) {
|
||||||
|
lock();
|
||||||
|
iter found = find(host);
|
||||||
|
bool r = (found != blacklist.end()) && (found->errorCount > MAX_ERRORCOUNT);
|
||||||
|
unlock();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add(LLHost& host, float timeout, U32 reason) {
|
||||||
|
BlackListEntry entry;
|
||||||
|
entry.host = host;
|
||||||
|
entry.timeUntil = clock() + timeout*CLOCKS_PER_SEC;
|
||||||
|
entry.reason = reason;
|
||||||
|
entry.errorCount = 0;
|
||||||
|
lock();
|
||||||
|
iter found = find(host);
|
||||||
|
if(found != blacklist.end()) {
|
||||||
|
entry.errorCount = found->errorCount + 1;
|
||||||
|
*found = entry;
|
||||||
|
}
|
||||||
|
else blacklist.push_back(entry);
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LLMutex* SGHostBlackList::sMutex = 0;
|
||||||
|
SGHostBlackList::blacklist_t SGHostBlackList::blacklist;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//static
|
//static
|
||||||
const char* LLTextureFetchWorker::sStateDescs[] = {
|
const char* LLTextureFetchWorker::sStateDescs[] = {
|
||||||
"INVALID",
|
"INVALID",
|
||||||
@@ -766,6 +838,8 @@ bool LLTextureFetchWorker::doWork(S32 param)
|
|||||||
|
|
||||||
if (!mUrl.empty()) get_url = false;
|
if (!mUrl.empty()) get_url = false;
|
||||||
// if (mHost != LLHost::invalid) get_url = false;
|
// if (mHost != LLHost::invalid) get_url = false;
|
||||||
|
if (SGHostBlackList::isBlacklisted(mHost)) get_url = false;
|
||||||
|
|
||||||
if ( get_url && mCanUseHTTP && mUrl.empty())//get http url.
|
if ( get_url && mCanUseHTTP && mUrl.empty())//get http url.
|
||||||
{
|
{
|
||||||
LLViewerRegion* region = NULL;
|
LLViewerRegion* region = NULL;
|
||||||
@@ -928,10 +1002,19 @@ bool LLTextureFetchWorker::doWork(S32 param)
|
|||||||
if (mRequestedSize < 0)
|
if (mRequestedSize < 0)
|
||||||
{
|
{
|
||||||
S32 max_attempts;
|
S32 max_attempts;
|
||||||
if (mGetStatus == HTTP_NOT_FOUND)
|
if (mGetStatus == HTTP_NOT_FOUND || mGetStatus == 499 || mGetStatus == HTTP_SERVICE_UNAVAILABLE)
|
||||||
{
|
{
|
||||||
mHTTPFailCount = max_attempts = 1; // Don't retry
|
mHTTPFailCount = max_attempts = 1; // Don't retry
|
||||||
llwarns << "Texture missing from server (404): " << mUrl << llendl;
|
if(mGetStatus == HTTP_NOT_FOUND)
|
||||||
|
llwarns << "Texture missing from server (404): " << mUrl << llendl;
|
||||||
|
else if (mGetStatus == 499) {
|
||||||
|
llwarns << "No response from server (499): " << mUrl << llendl;
|
||||||
|
SGHostBlackList::add(mHost, 60.0, mGetStatus);
|
||||||
|
}
|
||||||
|
else if (mGetStatus == HTTP_SERVICE_UNAVAILABLE){
|
||||||
|
llwarns << "Texture server busy (503): " << mUrl << LL_ENDL;
|
||||||
|
SGHostBlackList::add(mHost, 60.0, mGetStatus);
|
||||||
|
}
|
||||||
|
|
||||||
//roll back to try UDP
|
//roll back to try UDP
|
||||||
if(mCanUseNET)
|
if(mCanUseNET)
|
||||||
@@ -948,18 +1031,18 @@ bool LLTextureFetchWorker::doWork(S32 param)
|
|||||||
return true; // failed
|
return true; // failed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mGetStatus == HTTP_SERVICE_UNAVAILABLE)
|
//else if (mGetStatus == HTTP_SERVICE_UNAVAILABLE)
|
||||||
{
|
//{
|
||||||
// *TODO: Should probably introduce a timer here to delay future HTTP requsts
|
// // *TODO: Should probably introduce a timer here to delay future HTTP requsts
|
||||||
// for a short time (~1s) to ease server load? Ideally the server would queue
|
// // 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.
|
// // requests instead of returning 503... we already limit the number pending.
|
||||||
++mHTTPFailCount;
|
// ++mHTTPFailCount;
|
||||||
max_attempts = mHTTPFailCount+1; // Keep retrying
|
// max_attempts = mHTTPFailCount+1; // Keep retrying
|
||||||
LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL;
|
// LL_INFOS_ONCE("Texture") << "Texture server busy (503): " << mUrl << LL_ENDL;
|
||||||
}
|
//}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const S32 HTTP_MAX_RETRY_COUNT = 3;
|
const S32 HTTP_MAX_RETRY_COUNT = 1;
|
||||||
max_attempts = HTTP_MAX_RETRY_COUNT + 1;
|
max_attempts = HTTP_MAX_RETRY_COUNT + 1;
|
||||||
++mHTTPFailCount;
|
++mHTTPFailCount;
|
||||||
llinfos << "HTTP GET failed for: " << mUrl
|
llinfos << "HTTP GET failed for: " << mUrl
|
||||||
|
|||||||
Reference in New Issue
Block a user