SH-4478 Corrected/updated error handling for all retrieval operations.

Fri, 06 Sep 2013 16:37:31 -0400

author
Monty Brandenberg <monty@lindenlab.com>
date
Fri, 06 Sep 2013 16:37:31 -0400
changeset 40720
2ebe6a72a502
parent 40719
2001bebae60f
child 40721
e9454aeb9ec3

SH-4478 Corrected/updated error handling for all retrieval operations.
In case of HTTP errors or parsing/processing errors, fail the
fetch request rather than do a retry spin. Add logging for all
such failure paths. Added a development/debug flag to create
probabilistic failures to test these modes and general error
recovery by higher-level layers.

indra/newview/llmeshrepository.cpp file | annotate | diff | revisions
     1.1 --- a/indra/newview/llmeshrepository.cpp	Thu Aug 29 13:04:05 2013 -0400
     1.2 +++ b/indra/newview/llmeshrepository.cpp	Fri Sep 06 16:37:31 2013 -0400
     1.3 @@ -44,6 +44,7 @@
     1.4  #include "lleconomy.h"
     1.5  #include "llimagej2c.h"
     1.6  #include "llhost.h"
     1.7 +#include "llmath.h"
     1.8  #include "llnotificationsutil.h"
     1.9  #include "llsd.h"
    1.10  #include "llsdutil_math.h"
    1.11 @@ -284,72 +285,10 @@
    1.12  //   * Need a final failure state for requests that are retried and just won't
    1.13  //     complete.  We can fail a LOD request, others we don't.
    1.14  
    1.15 -LLMeshRepository gMeshRepo;
    1.16 -
    1.17 -const S32 MESH_HEADER_SIZE = 4096;                      // Important:  assumption is that headers fit in this space
    1.18 -const S32 REQUEST_HIGH_WATER_MIN = 32;					// Limits for GetMesh regions
    1.19 -const S32 REQUEST_HIGH_WATER_MAX = 150;					// Should remain under 2X throttle
    1.20 -const S32 REQUEST_LOW_WATER_MIN = 16;
    1.21 -const S32 REQUEST_LOW_WATER_MAX = 75;
    1.22 -const S32 REQUEST2_HIGH_WATER_MIN = 32;					// Limits for GetMesh2 regions
    1.23 -const S32 REQUEST2_HIGH_WATER_MAX = 80;
    1.24 -const S32 REQUEST2_LOW_WATER_MIN = 16;
    1.25 -const S32 REQUEST2_LOW_WATER_MAX = 40;
    1.26 -const U32 LARGE_MESH_FETCH_THRESHOLD = 1U << 21;		// Size at which requests goes to narrow/slow queue
    1.27 -const long SMALL_MESH_XFER_TIMEOUT = 60L;				// Seconds to complete xfer, small mesh downloads
    1.28 -const long LARGE_MESH_XFER_TIMEOUT = 600L;				// Seconds to complete xfer, large downloads
    1.29 -
    1.30 -// Maximum mesh version to support.  Three least significant digits are reserved for the minor version, 
    1.31 -// with major version changes indicating a format change that is not backwards compatible and should not
    1.32 -// be parsed by viewers that don't specifically support that version. For example, if the integer "1" is 
    1.33 -// present, the version is 0.001. A viewer that can parse version 0.001 can also parse versions up to 0.999, 
    1.34 -// but not 1.0 (integer 1000).
    1.35 -// See wiki at https://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format
    1.36 -const S32 MAX_MESH_VERSION = 999;
    1.37 -
    1.38 -U32 LLMeshRepository::sBytesReceived = 0;
    1.39 -U32 LLMeshRepository::sMeshRequestCount = 0;
    1.40 -U32 LLMeshRepository::sHTTPRequestCount = 0;
    1.41 -U32 LLMeshRepository::sHTTPLargeRequestCount = 0;
    1.42 -U32 LLMeshRepository::sHTTPRetryCount = 0;
    1.43 -U32 LLMeshRepository::sHTTPErrorCount = 0;
    1.44 -U32 LLMeshRepository::sLODProcessing = 0;
    1.45 -U32 LLMeshRepository::sLODPending = 0;
    1.46 -
    1.47 -U32 LLMeshRepository::sCacheBytesRead = 0;
    1.48 -U32 LLMeshRepository::sCacheBytesWritten = 0;
    1.49 -U32 LLMeshRepository::sCacheReads = 0;
    1.50 -U32 LLMeshRepository::sCacheWrites = 0;
    1.51 -U32 LLMeshRepository::sMaxLockHoldoffs = 0;
    1.52 -
    1.53 -LLDeadmanTimer LLMeshRepository::sQuiescentTimer(15.0, false);	// true -> gather cpu metrics
    1.54 -
    1.55 -	
    1.56 -static S32 dump_num = 0;
    1.57 -std::string make_dump_name(std::string prefix, S32 num)
    1.58 -{
    1.59 -	return prefix + boost::lexical_cast<std::string>(num) + std::string(".xml");
    1.60 -	
    1.61 -}
    1.62 -void dump_llsd_to_file(const LLSD& content, std::string filename);
    1.63 -LLSD llsd_from_file(std::string filename);
    1.64 -
    1.65 -const std::string header_lod[] = 
    1.66 -{
    1.67 -	"lowest_lod",
    1.68 -	"low_lod",
    1.69 -	"medium_lod",
    1.70 -	"high_lod"
    1.71 -};
    1.72 -const char * const LOG_MESH = "Mesh";
    1.73 -
    1.74 -// Static data and functions to measure mesh load
    1.75 -// time metrics for a new region scene.
    1.76 -static unsigned int metrics_teleport_start_count = 0;
    1.77 -boost::signals2::connection metrics_teleport_started_signal;
    1.78 -static void teleport_started();
    1.79 -static bool is_retryable(LLCore::HttpStatus status);
    1.80 -
    1.81 +
    1.82 +// --------------------------------------------------------------------------
    1.83 +//                    Development/Debug/QA Tools
    1.84 +//
    1.85  // Enable here or in build environment to get fasttimer data on mesh fetches.
    1.86  //
    1.87  // Typically, this is used to perform A/B testing using the
    1.88 @@ -368,7 +307,95 @@
    1.89  #else
    1.90  #define	MESH_FASTTIMER_DEFBLOCK
    1.91  #endif // LL_MESH_FASTTIMER_ENABLE
    1.92 - 
    1.93 +
    1.94 +
    1.95 +// Random failure testing for development/QA.
    1.96 +//
    1.97 +// Set the MESH_*_FAILED macros to either 'false' or to
    1.98 +// an invocation of MESH_RANDOM_NTH_TRUE() with some
    1.99 +// suitable number.  In production, all must be false.
   1.100 +//
   1.101 +// Example:
   1.102 +// #define	MESH_HTTP_RESPONSE_FAILED				MESH_RANDOM_NTH_TRUE(9)
   1.103 +
   1.104 +// 1-in-N calls will test true
   1.105 +#define	MESH_RANDOM_NTH_TRUE(_N)				( ll_rand(S32(_N)) == 0 )
   1.106 +
   1.107 +#define	MESH_HTTP_RESPONSE_FAILED				false
   1.108 +#define	MESH_HEADER_PROCESS_FAILED				false
   1.109 +#define	MESH_LOD_PROCESS_FAILED					false
   1.110 +#define	MESH_SKIN_INFO_PROCESS_FAILED			false
   1.111 +#define	MESH_DECOMP_PROCESS_FAILED				false
   1.112 +#define MESH_PHYS_SHAPE_PROCESS_FAILED			false
   1.113 +
   1.114 +// --------------------------------------------------------------------------
   1.115 +
   1.116 +
   1.117 +LLMeshRepository gMeshRepo;
   1.118 +
   1.119 +const S32 MESH_HEADER_SIZE = 4096;                      // Important:  assumption is that headers fit in this space
   1.120 +const S32 REQUEST_HIGH_WATER_MIN = 32;					// Limits for GetMesh regions
   1.121 +const S32 REQUEST_HIGH_WATER_MAX = 150;					// Should remain under 2X throttle
   1.122 +const S32 REQUEST_LOW_WATER_MIN = 16;
   1.123 +const S32 REQUEST_LOW_WATER_MAX = 75;
   1.124 +const S32 REQUEST2_HIGH_WATER_MIN = 32;					// Limits for GetMesh2 regions
   1.125 +const S32 REQUEST2_HIGH_WATER_MAX = 80;
   1.126 +const S32 REQUEST2_LOW_WATER_MIN = 16;
   1.127 +const S32 REQUEST2_LOW_WATER_MAX = 40;
   1.128 +const U32 LARGE_MESH_FETCH_THRESHOLD = 1U << 21;		// Size at which requests goes to narrow/slow queue
   1.129 +const long SMALL_MESH_XFER_TIMEOUT = 60L;				// Seconds to complete xfer, small mesh downloads
   1.130 +const long LARGE_MESH_XFER_TIMEOUT = 600L;				// Seconds to complete xfer, large downloads
   1.131 +
   1.132 +// Maximum mesh version to support.  Three least significant digits are reserved for the minor version, 
   1.133 +// with major version changes indicating a format change that is not backwards compatible and should not
   1.134 +// be parsed by viewers that don't specifically support that version. For example, if the integer "1" is 
   1.135 +// present, the version is 0.001. A viewer that can parse version 0.001 can also parse versions up to 0.999, 
   1.136 +// but not 1.0 (integer 1000).
   1.137 +// See wiki at https://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format
   1.138 +const S32 MAX_MESH_VERSION = 999;
   1.139 +
   1.140 +U32 LLMeshRepository::sBytesReceived = 0;
   1.141 +U32 LLMeshRepository::sMeshRequestCount = 0;
   1.142 +U32 LLMeshRepository::sHTTPRequestCount = 0;
   1.143 +U32 LLMeshRepository::sHTTPLargeRequestCount = 0;
   1.144 +U32 LLMeshRepository::sHTTPRetryCount = 0;
   1.145 +U32 LLMeshRepository::sHTTPErrorCount = 0;
   1.146 +U32 LLMeshRepository::sLODProcessing = 0;
   1.147 +U32 LLMeshRepository::sLODPending = 0;
   1.148 +
   1.149 +U32 LLMeshRepository::sCacheBytesRead = 0;
   1.150 +U32 LLMeshRepository::sCacheBytesWritten = 0;
   1.151 +U32 LLMeshRepository::sCacheReads = 0;
   1.152 +U32 LLMeshRepository::sCacheWrites = 0;
   1.153 +U32 LLMeshRepository::sMaxLockHoldoffs = 0;
   1.154 +
   1.155 +LLDeadmanTimer LLMeshRepository::sQuiescentTimer(15.0, false);	// true -> gather cpu metrics
   1.156 +
   1.157 +	
   1.158 +static S32 dump_num = 0;
   1.159 +std::string make_dump_name(std::string prefix, S32 num)
   1.160 +{
   1.161 +	return prefix + boost::lexical_cast<std::string>(num) + std::string(".xml");
   1.162 +	
   1.163 +}
   1.164 +void dump_llsd_to_file(const LLSD& content, std::string filename);
   1.165 +LLSD llsd_from_file(std::string filename);
   1.166 +
   1.167 +const std::string header_lod[] = 
   1.168 +{
   1.169 +	"lowest_lod",
   1.170 +	"low_lod",
   1.171 +	"medium_lod",
   1.172 +	"high_lod"
   1.173 +};
   1.174 +const char * const LOG_MESH = "Mesh";
   1.175 +
   1.176 +// Static data and functions to measure mesh load
   1.177 +// time metrics for a new region scene.
   1.178 +static unsigned int metrics_teleport_start_count = 0;
   1.179 +boost::signals2::connection metrics_teleport_started_signal;
   1.180 +static void teleport_started();
   1.181 +
   1.182  //get the number of bytes resident in memory for given volume
   1.183  U32 get_volume_memory_size(const LLVolume* volume)
   1.184  {
   1.185 @@ -815,7 +842,7 @@
   1.186  			mLODReqQ.pop();
   1.187  			LLMeshRepository::sLODProcessing--;
   1.188  			mMutex->unlock();
   1.189 -			if (!fetchMeshLOD(req.mMeshParams, req.mLOD))//failed, resubmit
   1.190 +			if (!fetchMeshLOD(req.mMeshParams, req.mLOD))		// failed, resubmit
   1.191  			{
   1.192  				mMutex->lock();
   1.193  				mLODReqQ.push(req) ; 
   1.194 @@ -1548,6 +1575,7 @@
   1.195  				{
   1.196  					handler->mHttpHandle = handle;
   1.197  					mHttpRequestSet.insert(handler);
   1.198 +					// *NOTE:  Allowing a re-request, not marking as unavailable.  Is that correct?
   1.199  				}
   1.200  			}
   1.201  			else
   1.202 @@ -2529,7 +2557,7 @@
   1.203  	LLMeshRepository::sHTTPRetryCount += retries;
   1.204  
   1.205  	LLCore::HttpStatus status(response->getStatus());
   1.206 -	if (! status)
   1.207 +	if (! status || MESH_HTTP_RESPONSE_FAILED)
   1.208  	{
   1.209  		processFailure(status);
   1.210  		++LLMeshRepository::sHTTPErrorCount;
   1.211 @@ -2600,39 +2628,37 @@
   1.212  
   1.213  void LLMeshHeaderHandler::processFailure(LLCore::HttpStatus status)
   1.214  {
   1.215 -	if (is_retryable(status))
   1.216 +	LL_WARNS(LOG_MESH) << "Error during mesh header handling.  ID:  " << mMeshParams.getSculptID()
   1.217 +					   << ", Reason:  " << status.toString()
   1.218 +					   << " (" << status.toHex() << ").  Not retrying."
   1.219 +					   << LL_ENDL;
   1.220 +
   1.221 +	// Can't get the header so none of the LODs will be available
   1.222 +	LLMutexLock lock(gMeshRepo.mThread->mMutex);
   1.223 +	for (int i(0); i < 4; ++i)
   1.224  	{
   1.225 -		// *TODO:  This and the other processFailure() methods should
   1.226 -		// probably just fail hard (as llcorehttp has done the retries).
   1.227 -		// Or we could implement a slow/forever retry class.
   1.228 -		
   1.229 -		LL_WARNS(LOG_MESH) << "Error during mesh header handling.  Reason:  " << status.toString()
   1.230 -						   << " (" << status.toHex() << ").  Retrying."
   1.231 -						   << LL_ENDL;
   1.232 -		LLMeshRepoThread::HeaderRequest req(mMeshParams);
   1.233 -		LLMutexLock lock(gMeshRepo.mThread->mMutex);
   1.234 -		gMeshRepo.mThread->mHeaderReqQ.push(req);
   1.235 -	}
   1.236 -	else
   1.237 -	{
   1.238 -		// *TODO:  Mark mesh unavailable
   1.239 -		LL_WARNS(LOG_MESH) << "Error during mesh header handling.  Reason:  " << status.toString()
   1.240 -						   << " (" << status.toHex() << ").  Not retrying."
   1.241 -						   << LL_ENDL;
   1.242 +		gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i));
   1.243  	}
   1.244  }
   1.245  
   1.246  void LLMeshHeaderHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size)
   1.247  {
   1.248  	LLUUID mesh_id = mMeshParams.getSculptID();
   1.249 -	bool success = gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size);
   1.250 +	bool success = (! MESH_HEADER_PROCESS_FAILED) && gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size);
   1.251  	llassert(success);
   1.252  	if (! success)
   1.253  	{
   1.254 -		// *TODO:  Mark mesh unavailable
   1.255 -		// *TODO:  Get real reason for parse failure here
   1.256 +		// *TODO:  Get real reason for parse failure here.  Might we want to retry?
   1.257  		LL_WARNS(LOG_MESH) << "Unable to parse mesh header.  ID:  " << mesh_id
   1.258 +						   << ", Unknown reason.  Not retrying."
   1.259  						   << LL_ENDL;
   1.260 +
   1.261 +		// Can't get the header so none of the LODs will be available
   1.262 +		LLMutexLock lock(gMeshRepo.mThread->mMutex);
   1.263 +		for (int i(0); i < 4; ++i)
   1.264 +		{
   1.265 +			gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i));
   1.266 +		}
   1.267  	}
   1.268  	else if (data && data_size > 0)
   1.269  	{
   1.270 @@ -2708,29 +2734,18 @@
   1.271  
   1.272  void LLMeshLODHandler::processFailure(LLCore::HttpStatus status)
   1.273  {
   1.274 -	if (is_retryable(status))
   1.275 -	{
   1.276 -		LL_WARNS(LOG_MESH) << "Error during mesh header handling.  Reason:  " << status.toString()
   1.277 -						   << " (" << status.toHex() << ").  Retrying."
   1.278 -						   << LL_ENDL;
   1.279 -		{
   1.280 -			LLMutexLock lock(gMeshRepo.mThread->mMutex);
   1.281 -
   1.282 -			gMeshRepo.mThread->loadMeshLOD(mMeshParams, mLOD);
   1.283 -		}
   1.284 -	}
   1.285 -	else
   1.286 -	{
   1.287 -		// *TODO:  Mark mesh unavailable
   1.288 -		LL_WARNS(LOG_MESH) << "Error during mesh LOD handling.  Reason:  " << status.toString()
   1.289 -						   << " (" << status.toHex() << ").  Not retrying."
   1.290 -						   << LL_ENDL;
   1.291 -	}
   1.292 +	LL_WARNS(LOG_MESH) << "Error during mesh LOD handling.  ID:  " << mMeshParams.getSculptID()
   1.293 +					   << ", Reason:  " << status.toString()
   1.294 +					   << " (" << status.toHex() << ").  Not retrying."
   1.295 +					   << LL_ENDL;
   1.296 +
   1.297 +	LLMutexLock lock(gMeshRepo.mThread->mMutex);
   1.298 +	gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
   1.299  }
   1.300  
   1.301  void LLMeshLODHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size)
   1.302  {
   1.303 -	if (gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size))
   1.304 +	if ((! MESH_LOD_PROCESS_FAILED) && gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size))
   1.305  	{
   1.306  		// good fetch from sim, write to VFS for caching
   1.307  		LLVFile file(gVFS, mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLVFile::WRITE);
   1.308 @@ -2746,7 +2761,14 @@
   1.309  			++LLMeshRepository::sCacheWrites;
   1.310  		}
   1.311  	}
   1.312 -	// *TODO:  Mark mesh unavailable on error
   1.313 +	else
   1.314 +	{
   1.315 +		LL_WARNS(LOG_MESH) << "Error during mesh LOD processing.  ID:  " << mMeshParams.getSculptID()
   1.316 +						   << ", Unknown reason.  Not retrying."
   1.317 +						   << LL_ENDL;
   1.318 +		LLMutexLock lock(gMeshRepo.mThread->mMutex);
   1.319 +		gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD));
   1.320 +	}
   1.321  }
   1.322  
   1.323  LLMeshSkinInfoHandler::~LLMeshSkinInfoHandler()
   1.324 @@ -2756,29 +2778,18 @@
   1.325  
   1.326  void LLMeshSkinInfoHandler::processFailure(LLCore::HttpStatus status)
   1.327  {
   1.328 -	if (is_retryable(status))
   1.329 -	{
   1.330 -		LL_WARNS(LOG_MESH) << "Error during mesh skin info handling.  Reason:  " << status.toString()
   1.331 -						   << " (" << status.toHex() << ").  Retrying."
   1.332 -						   << LL_ENDL;
   1.333 -		{
   1.334 -			LLMutexLock lock(gMeshRepo.mThread->mMutex);
   1.335 -
   1.336 -			gMeshRepo.mThread->loadMeshSkinInfo(mMeshID);
   1.337 -		}
   1.338 -	}
   1.339 -	else
   1.340 -	{
   1.341 -		// *TODO:  Mark mesh unavailable on error
   1.342 -		LL_WARNS(LOG_MESH) << "Error during mesh skin info handling.  Reason:  " << status.toString()
   1.343 -						   << " (" << status.toHex() << ").  Not retrying."
   1.344 -						   << LL_ENDL;
   1.345 -	}
   1.346 +	LL_WARNS(LOG_MESH) << "Error during mesh skin info handling.  ID:  " << mMeshID
   1.347 +					   << ", Reason:  " << status.toString()
   1.348 +					   << " (" << status.toHex() << ").  Not retrying."
   1.349 +					   << LL_ENDL;
   1.350 +
   1.351 +	// *TODO:  Mark mesh unavailable on error.  For now, simply leave
   1.352 +	// request unfulfilled rather than retry forever.
   1.353  }
   1.354  
   1.355  void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size)
   1.356  {
   1.357 -	if (gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size))
   1.358 +	if ((! MESH_SKIN_INFO_PROCESS_FAILED) && gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size))
   1.359  	{
   1.360  		// good fetch from sim, write to VFS for caching
   1.361  		LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE);
   1.362 @@ -2794,7 +2805,13 @@
   1.363  			file.write(data, size);
   1.364  		}
   1.365  	}
   1.366 -	// *TODO:  Mark mesh unavailable on error
   1.367 +	else
   1.368 +	{
   1.369 +		LL_WARNS(LOG_MESH) << "Error during mesh skin info processing.  ID:  " << mMeshID
   1.370 +						   << ", Unknown reason.  Not retrying."
   1.371 +						   << LL_ENDL;
   1.372 +		// *TODO:  Mark mesh unavailable on error
   1.373 +	}
   1.374  }
   1.375  
   1.376  LLMeshDecompositionHandler::~LLMeshDecompositionHandler()
   1.377 @@ -2804,29 +2821,17 @@
   1.378  
   1.379  void LLMeshDecompositionHandler::processFailure(LLCore::HttpStatus status)
   1.380  {
   1.381 -	if (is_retryable(status))
   1.382 -	{
   1.383 -		LL_WARNS(LOG_MESH) << "Error during mesh decomposition handling.  Reason:  " << status.toString()
   1.384 -						   << " (" << status.toHex() << ").  Retrying."
   1.385 -						   << LL_ENDL;
   1.386 -		{
   1.387 -			LLMutexLock lock(gMeshRepo.mThread->mMutex);
   1.388 -
   1.389 -			gMeshRepo.mThread->loadMeshDecomposition(mMeshID);
   1.390 -		}
   1.391 -	}
   1.392 -	else
   1.393 -	{
   1.394 -		// *TODO:  Mark mesh unavailable on error
   1.395 -		LL_WARNS(LOG_MESH) << "Error during mesh decomposition handling.  Reason:  " << status.toString()
   1.396 -						   << " (" << status.toHex() << ").  Not retrying."
   1.397 -						   << LL_ENDL;
   1.398 -	}
   1.399 +	LL_WARNS(LOG_MESH) << "Error during mesh decomposition handling.  ID:  " << mMeshID
   1.400 +					   << ", Reason:  " << status.toString()
   1.401 +					   << " (" << status.toHex() << ").  Not retrying."
   1.402 +					   << LL_ENDL;
   1.403 +	// *TODO:  Mark mesh unavailable on error.  For now, simply leave
   1.404 +	// request unfulfilled rather than retry forever.
   1.405  }
   1.406  
   1.407  void LLMeshDecompositionHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size)
   1.408  {
   1.409 -	if (gMeshRepo.mThread->decompositionReceived(mMeshID, data, data_size))
   1.410 +	if ((! MESH_DECOMP_PROCESS_FAILED) && gMeshRepo.mThread->decompositionReceived(mMeshID, data, data_size))
   1.411  	{
   1.412  		// good fetch from sim, write to VFS for caching
   1.413  		LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE);
   1.414 @@ -2842,7 +2847,13 @@
   1.415  			file.write(data, size);
   1.416  		}
   1.417  	}
   1.418 -	// *TODO:  Mark mesh unavailable on error
   1.419 +	else
   1.420 +	{
   1.421 +		LL_WARNS(LOG_MESH) << "Error during mesh decomposition processing.  ID:  " << mMeshID
   1.422 +						   << ", Unknown reason.  Not retrying."
   1.423 +						   << LL_ENDL;
   1.424 +		// *TODO:  Mark mesh unavailable on error
   1.425 +	}
   1.426  }
   1.427  
   1.428  LLMeshPhysicsShapeHandler::~LLMeshPhysicsShapeHandler()
   1.429 @@ -2852,29 +2863,16 @@
   1.430  
   1.431  void LLMeshPhysicsShapeHandler::processFailure(LLCore::HttpStatus status)
   1.432  {
   1.433 -	if (is_retryable(status))
   1.434 -	{
   1.435 -		LL_WARNS(LOG_MESH) << "Error during mesh physics shape handling.  Reason:  " << status.toString()
   1.436 -						   << " (" << status.toHex() << ").  Retrying."
   1.437 -						   << LL_ENDL;
   1.438 -		{
   1.439 -			LLMutexLock lock(gMeshRepo.mThread->mMutex);
   1.440 -
   1.441 -			gMeshRepo.mThread->loadMeshPhysicsShape(mMeshID);
   1.442 -		}
   1.443 -	}
   1.444 -	else
   1.445 -	{
   1.446 -		// *TODO:  Mark mesh unavailable on error
   1.447 -		LL_WARNS(LOG_MESH) << "Error during mesh physics shape handling.  Reason:  " << status.toString()
   1.448 -						   << " (" << status.toHex() << ").  Not retrying."
   1.449 -						   << LL_ENDL;
   1.450 -	}
   1.451 +	LL_WARNS(LOG_MESH) << "Error during mesh physics shape handling.  ID:  " << mMeshID
   1.452 +					   << ", Reason:  " << status.toString()
   1.453 +					   << " (" << status.toHex() << ").  Not retrying."
   1.454 +					   << LL_ENDL;
   1.455 +	// *TODO:  Mark mesh unavailable on error
   1.456  }
   1.457  
   1.458  void LLMeshPhysicsShapeHandler::processData(LLCore::BufferArray * body, U8 * data, S32 data_size)
   1.459  {
   1.460 -	if (gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size))
   1.461 +	if ((! MESH_PHYS_SHAPE_PROCESS_FAILED) && gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size))
   1.462  	{
   1.463  		// good fetch from sim, write to VFS for caching
   1.464  		LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE);
   1.465 @@ -2890,7 +2888,13 @@
   1.466  			file.write(data, size);
   1.467  		}
   1.468  	}
   1.469 -	// *TODO:  Mark mesh unavailable on error
   1.470 +	else
   1.471 +	{
   1.472 +		LL_WARNS(LOG_MESH) << "Error during mesh physics shape processing.  ID:  " << mMeshID
   1.473 +						   << ", Unknown reason.  Not retrying."
   1.474 +						   << LL_ENDL;
   1.475 +		// *TODO:  Mark mesh unavailable on error
   1.476 +	}
   1.477  }
   1.478  
   1.479  LLMeshRepository::LLMeshRepository()
   1.480 @@ -3000,7 +3004,7 @@
   1.481  	// Manage time-to-load metrics for mesh download operations.
   1.482  	metricsProgress(1);
   1.483  
   1.484 -	if (detail < 0 || detail > 4)
   1.485 +	if (detail < 0 || detail >= 4)
   1.486  	{
   1.487  		return detail;
   1.488  	}
   1.489 @@ -4439,32 +4443,3 @@
   1.490  	LLMeshRepository::metricsStart();
   1.491  }
   1.492  
   1.493 -// *TODO:  This comes from an edit in viewer-cat.  Unify this once that's
   1.494 -// available everywhere.
   1.495 -bool is_retryable(LLCore::HttpStatus status)
   1.496 -{
   1.497 -	static const LLCore::HttpStatus cant_connect(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);
   1.498 -	static const LLCore::HttpStatus cant_res_proxy(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_PROXY);
   1.499 -	static const LLCore::HttpStatus cant_res_host(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_HOST);
   1.500 -	static const LLCore::HttpStatus send_error(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_SEND_ERROR);
   1.501 -	static const LLCore::HttpStatus recv_error(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_RECV_ERROR);
   1.502 -	static const LLCore::HttpStatus upload_failed(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_UPLOAD_FAILED);
   1.503 -	static const LLCore::HttpStatus op_timedout(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);
   1.504 -	static const LLCore::HttpStatus post_error(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_HTTP_POST_ERROR);
   1.505 -	static const LLCore::HttpStatus partial_file(LLCore::HttpStatus::EXT_CURL_EASY, CURLE_PARTIAL_FILE);
   1.506 -	static const LLCore::HttpStatus inv_cont_range(LLCore::HttpStatus::LLCORE, LLCore::HE_INV_CONTENT_RANGE_HDR);
   1.507 -	
   1.508 -	return ((! status) &&
   1.509 -			((status.isHttpStatus() && status.mType >= 499 && status.mType <= 599) ||		// Include special 499 in retryables
   1.510 -			 status == cant_connect ||			// Connection reset/endpoint problems
   1.511 -			 status == cant_res_proxy ||		// DNS problems
   1.512 -			 status == cant_res_host ||			// DNS problems
   1.513 -			 status == send_error ||			// General socket problems
   1.514 -			 status == recv_error ||			// General socket problems
   1.515 -			 status == upload_failed ||			// Transport problem
   1.516 -			 status == op_timedout ||			// Timer expired
   1.517 -			 status == post_error ||			// Transport problem
   1.518 -			 status == partial_file ||			// Data inconsistency in response
   1.519 -			 status == inv_cont_range));		// Short data read disagrees with content-range
   1.520 -}
   1.521 -

mercurial