SH-3690 SH-4505 Cleanup pass through code.

Tue, 24 Sep 2013 14:49:26 -0400

author
Monty Brandenberg <monty@lindenlab.com>
date
Tue, 24 Sep 2013 14:49:26 -0400
changeset 40730
cb203df9d1b2
parent 40729
6dd49a6d7675
child 40731
61f491773403

SH-3690 SH-4505 Cleanup pass through code.
Start using DNS cache in legacy LLCurl code. Go to 15 seconds
particularly as we're using threaded resolver at this point.
Documentation cleanup. Add libcurl status checking and logging
for curl_easy_setopt() operations that fail. Shouldn't happen
and we'll just continue anyway but there's info in the logs to
track these down now. Cleaned up logic around FASTTIMER enable
defines used to evaluate pipeline stalls in main thread.
Removed long-standing thread race around caps strings and
URL construction. Not a significant risk but refactoring the
code to get rid of them removed one huge eyesore. It can be
made even slicker if desired (see notes).

indra/llcorehttp/_httpoperation.cpp file | annotate | diff | revisions
indra/llcorehttp/_httpoprequest.cpp file | annotate | diff | revisions
indra/llcorehttp/httpcommon.cpp file | annotate | diff | revisions
indra/llcorehttp/httpcommon.h file | annotate | diff | revisions
indra/llmessage/llcurl.cpp file | annotate | diff | revisions
indra/newview/llmeshrepository.cpp file | annotate | diff | revisions
indra/newview/llmeshrepository.h file | annotate | diff | revisions
     1.1 --- a/indra/llcorehttp/_httpoperation.cpp	Fri Sep 20 07:13:14 2013 +0000
     1.2 +++ b/indra/llcorehttp/_httpoperation.cpp	Tue Sep 24 14:49:26 2013 -0400
     1.3 @@ -94,7 +94,7 @@
     1.4  	// Default implementation should never be called.  This
     1.5  	// indicates an operation making a transition that isn't
     1.6  	// defined.
     1.7 -	LL_ERRS("HttpCore") << "Default stageFromRequest method may not be called."
     1.8 +	LL_ERRS("CoreHttp") << "Default stageFromRequest method may not be called."
     1.9  						<< LL_ENDL;
    1.10  }
    1.11  
    1.12 @@ -104,7 +104,7 @@
    1.13  	// Default implementation should never be called.  This
    1.14  	// indicates an operation making a transition that isn't
    1.15  	// defined.
    1.16 -	LL_ERRS("HttpCore") << "Default stageFromReady method may not be called."
    1.17 +	LL_ERRS("CoreHttp") << "Default stageFromReady method may not be called."
    1.18  						<< LL_ENDL;
    1.19  }
    1.20  
    1.21 @@ -114,7 +114,7 @@
    1.22  	// Default implementation should never be called.  This
    1.23  	// indicates an operation making a transition that isn't
    1.24  	// defined.
    1.25 -	LL_ERRS("HttpCore") << "Default stageFromActive method may not be called."
    1.26 +	LL_ERRS("CoreHttp") << "Default stageFromActive method may not be called."
    1.27  						<< LL_ENDL;
    1.28  }
    1.29  
     2.1 --- a/indra/llcorehttp/_httpoprequest.cpp	Fri Sep 20 07:13:14 2013 +0000
     2.2 +++ b/indra/llcorehttp/_httpoprequest.cpp	Tue Sep 24 14:49:26 2013 -0400
     2.3 @@ -90,6 +90,10 @@
     2.4  char * os_strltrim(char * str);
     2.5  void os_strlower(char * str);
     2.6  
     2.7 +// Error testing and reporting for libcurl status codes
     2.8 +void check_curl_easy_code(CURLcode code);
     2.9 +void check_curl_easy_code(CURLcode code, int curl_setopt_option);
    2.10 +
    2.11  } // end anonymous namespace
    2.12  
    2.13  
    2.14 @@ -373,6 +377,8 @@
    2.15  //
    2.16  HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
    2.17  {
    2.18 +	CURLcode code;
    2.19 +	
    2.20  	// Scrub transport and result data for retried op case
    2.21  	mCurlActive = false;
    2.22  	mCurlHandle = NULL;
    2.23 @@ -406,12 +412,25 @@
    2.24  	HttpPolicyGlobal & policy(service->getPolicy().getGlobalOptions());
    2.25  	
    2.26  	mCurlHandle = curl_easy_init();
    2.27 -	curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
    2.28 -	curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);
    2.29 -	curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
    2.30 -	curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
    2.31 -	curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this);
    2.32 -	curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
    2.33 +	if (! mCurlHandle)
    2.34 +	{
    2.35 +		// We're in trouble.  We'll continue but it won't go well.
    2.36 +		LL_WARNS("CoreHttp") << "Failed to allocate libcurl easy handle.  Continuing."
    2.37 +							 << LL_ENDL;
    2.38 +		return HttpStatus(HttpStatus::LLCORE, HE_BAD_ALLOC);
    2.39 +	}
    2.40 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
    2.41 +	check_curl_easy_code(code, CURLOPT_IPRESOLVE);
    2.42 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1);
    2.43 +	check_curl_easy_code(code, CURLOPT_NOSIGNAL);
    2.44 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
    2.45 +	check_curl_easy_code(code, CURLOPT_NOPROGRESS);
    2.46 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
    2.47 +	check_curl_easy_code(code, CURLOPT_URL);
    2.48 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this);
    2.49 +	check_curl_easy_code(code, CURLOPT_PRIVATE);
    2.50 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
    2.51 +	check_curl_easy_code(code, CURLOPT_ENCODING);
    2.52  
    2.53  	if (HTTP_ENABLE_LINKSYS_WRT54G_V5_DNS_FIX)
    2.54  	{
    2.55 @@ -421,7 +440,8 @@
    2.56  		// about 700 or so requests and starts issuing TCP RSTs to
    2.57  		// new connections.  Reuse the DNS lookups for even a few
    2.58  		// seconds and no RSTs.
    2.59 -		curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
    2.60 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
    2.61 +		check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
    2.62  	}
    2.63  	else
    2.64  	{
    2.65 @@ -429,17 +449,27 @@
    2.66  		// I don't think this is valid anymore, the Multi shared DNS
    2.67  		// cache is working well.  For the case of naked easy handles,
    2.68  		// consider using a shared DNS object.
    2.69 -		curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
    2.70 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
    2.71 +		check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
    2.72  	}
    2.73 -	curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
    2.74 -	curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1);
    2.75 -	curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
    2.76 -	curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
    2.77 -	curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, this);
    2.78 -	curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback);
    2.79 -	curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, this);
    2.80 -	curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);
    2.81 -	curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0);
    2.82 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
    2.83 +	check_curl_easy_code(code, CURLOPT_AUTOREFERER);
    2.84 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1);
    2.85 +	check_curl_easy_code(code, CURLOPT_FOLLOWLOCATION);
    2.86 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
    2.87 +	check_curl_easy_code(code, CURLOPT_MAXREDIRS);
    2.88 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback);
    2.89 +	check_curl_easy_code(code, CURLOPT_WRITEFUNCTION);
    2.90 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, this);
    2.91 +	check_curl_easy_code(code, CURLOPT_WRITEDATA);
    2.92 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback);
    2.93 +	check_curl_easy_code(code, CURLOPT_READFUNCTION);
    2.94 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, this);
    2.95 +	check_curl_easy_code(code, CURLOPT_READDATA);
    2.96 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1);
    2.97 +	check_curl_easy_code(code, CURLOPT_SSL_VERIFYPEER);
    2.98 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0);
    2.99 +	check_curl_easy_code(code, CURLOPT_SSL_VERIFYHOST);
   2.100  
   2.101  	if (policy.mUseLLProxy)
   2.102  	{
   2.103 @@ -452,37 +482,46 @@
   2.104  	{
   2.105  		// *TODO:  This is fine for now but get fuller socks5/
   2.106  		// authentication thing going later....
   2.107 -		curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, policy.mHttpProxy.c_str());
   2.108 -		curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
   2.109 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, policy.mHttpProxy.c_str());
   2.110 +		check_curl_easy_code(code, CURLOPT_PROXY);
   2.111 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
   2.112 +		check_curl_easy_code(code, CURLOPT_PROXYTYPE);
   2.113  	}
   2.114  	if (policy.mCAPath.size())
   2.115  	{
   2.116 -		curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, policy.mCAPath.c_str());
   2.117 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_CAPATH, policy.mCAPath.c_str());
   2.118 +		check_curl_easy_code(code, CURLOPT_CAPATH);
   2.119  	}
   2.120  	if (policy.mCAFile.size())
   2.121  	{
   2.122 -		curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, policy.mCAFile.c_str());
   2.123 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_CAINFO, policy.mCAFile.c_str());
   2.124 +		check_curl_easy_code(code, CURLOPT_CAINFO);
   2.125  	}
   2.126  	
   2.127  	switch (mReqMethod)
   2.128  	{
   2.129  	case HOR_GET:
   2.130 -		curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
   2.131 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPGET, 1);
   2.132 +		check_curl_easy_code(code, CURLOPT_HTTPGET);
   2.133  		mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
   2.134  		mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
   2.135  		break;
   2.136  		
   2.137  	case HOR_POST:
   2.138  		{
   2.139 -			curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1);
   2.140 -			curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
   2.141 +			code = curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1);
   2.142 +			check_curl_easy_code(code, CURLOPT_POST);
   2.143 +			code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
   2.144 +			check_curl_easy_code(code, CURLOPT_ENCODING);
   2.145  			long data_size(0);
   2.146  			if (mReqBody)
   2.147  			{
   2.148  				data_size = mReqBody->size();
   2.149  			}
   2.150 -			curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast<void *>(NULL));
   2.151 -			curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size);
   2.152 +			code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, static_cast<void *>(NULL));
   2.153 +			check_curl_easy_code(code, CURLOPT_POSTFIELDS);
   2.154 +			code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDSIZE, data_size);
   2.155 +			check_curl_easy_code(code, CURLOPT_POSTFIELDSIZE);
   2.156  			mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
   2.157  			mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
   2.158  			mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
   2.159 @@ -491,14 +530,17 @@
   2.160  		
   2.161  	case HOR_PUT:
   2.162  		{
   2.163 -			curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1);
   2.164 +			code = curl_easy_setopt(mCurlHandle, CURLOPT_UPLOAD, 1);
   2.165 +			check_curl_easy_code(code, CURLOPT_UPLOAD);
   2.166  			long data_size(0);
   2.167  			if (mReqBody)
   2.168  			{
   2.169  				data_size = mReqBody->size();
   2.170  			}
   2.171 -			curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
   2.172 -			curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
   2.173 +			code = curl_easy_setopt(mCurlHandle, CURLOPT_INFILESIZE, data_size);
   2.174 +			check_curl_easy_code(code, CURLOPT_INFILESIZE);
   2.175 +			code = curl_easy_setopt(mCurlHandle, CURLOPT_POSTFIELDS, (void *) NULL);
   2.176 +			check_curl_easy_code(code, CURLOPT_POSTFIELDS);
   2.177  			mCurlHeaders = curl_slist_append(mCurlHeaders, "Expect:");
   2.178  			mCurlHeaders = curl_slist_append(mCurlHeaders, "Connection: keep-alive");
   2.179  			mCurlHeaders = curl_slist_append(mCurlHeaders, "Keep-alive: 300");
   2.180 @@ -515,9 +557,12 @@
   2.181  	// Tracing
   2.182  	if (mTracing >= HTTP_TRACE_CURL_HEADERS)
   2.183  	{
   2.184 -		curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1);
   2.185 -		curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this);
   2.186 -		curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGFUNCTION, debugCallback);
   2.187 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_VERBOSE, 1);
   2.188 +		check_curl_easy_code(code, CURLOPT_VERBOSE);
   2.189 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGDATA, this);
   2.190 +		check_curl_easy_code(code, CURLOPT_DEBUGDATA);
   2.191 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_DEBUGFUNCTION, debugCallback);
   2.192 +		check_curl_easy_code(code, CURLOPT_DEBUGFUNCTION);
   2.193  	}
   2.194  	
   2.195  	// There's a CURLOPT for this now...
   2.196 @@ -557,8 +602,10 @@
   2.197  	{
   2.198  		xfer_timeout = timeout;
   2.199  	}
   2.200 -	curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout);
   2.201 -	curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout);
   2.202 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_TIMEOUT, xfer_timeout);
   2.203 +	check_curl_easy_code(code, CURLOPT_TIMEOUT);
   2.204 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_CONNECTTIMEOUT, timeout);
   2.205 +	check_curl_easy_code(code, CURLOPT_CONNECTTIMEOUT);
   2.206  
   2.207  	// Request headers
   2.208  	if (mReqHeaders)
   2.209 @@ -566,12 +613,15 @@
   2.210  		// Caller's headers last to override
   2.211  		mCurlHeaders = append_headers_to_slist(mReqHeaders, mCurlHeaders);
   2.212  	}
   2.213 -	curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders);
   2.214 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders);
   2.215 +	check_curl_easy_code(code, CURLOPT_HTTPHEADER);
   2.216  
   2.217  	if (mProcFlags & (PF_SCAN_RANGE_HEADER | PF_SAVE_HEADERS | PF_USE_RETRY_AFTER))
   2.218  	{
   2.219 -		curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback);
   2.220 -		curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this);
   2.221 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback);
   2.222 +		check_curl_easy_code(code, CURLOPT_HEADERFUNCTION);
   2.223 +		code = curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this);
   2.224 +		check_curl_easy_code(code, CURLOPT_HEADERDATA);
   2.225  	}
   2.226  	
   2.227  	if (status)
   2.228 @@ -612,7 +662,7 @@
   2.229  		{
   2.230  			// Warn but continue if the read position moves beyond end-of-body
   2.231  			// for some reason.
   2.232 -			LL_WARNS("HttpCore") << "Request body position beyond body size.  Truncating request body."
   2.233 +			LL_WARNS("CoreHttp") << "Request body position beyond body size.  Truncating request body."
   2.234  								 << LL_ENDL;
   2.235  		}
   2.236  		return 0;
   2.237 @@ -1046,6 +1096,32 @@
   2.238  }
   2.239  
   2.240  
   2.241 +void check_curl_easy_code(CURLcode code, int curl_setopt_option)
   2.242 +{
   2.243 +	if (CURLE_OK != code)
   2.244 +	{
   2.245 +		// Comment from old llcurl code which may no longer apply:
   2.246 +		//
   2.247 +		// linux appears to throw a curl error once per session for a bad initialization
   2.248 +		// at a pretty random time (when enabling cookies).
   2.249 +		LL_WARNS("CoreHttp") << "libcurl error detected:  " << curl_easy_strerror(code)
   2.250 +							 << ", curl_easy_setopt option:  " << curl_setopt_option
   2.251 +							 << LL_ENDL;
   2.252 +	}
   2.253 +}
   2.254 +
   2.255 +
   2.256 +void check_curl_easy_code(CURLcode code)
   2.257 +{
   2.258 +	if (CURLE_OK != code)
   2.259 +	{
   2.260 +		// Comment from old llcurl code which may no longer apply:
   2.261 +		//
   2.262 +		// linux appears to throw a curl error once per session for a bad initialization
   2.263 +		// at a pretty random time (when enabling cookies).
   2.264 +		LL_WARNS("CoreHttp") << "libcurl error detected:  " << curl_easy_strerror(code)
   2.265 +							 << LL_ENDL;
   2.266 +	}
   2.267 +}
   2.268 +
   2.269  }  // end anonymous namespace
   2.270 -
   2.271 -		
     3.1 --- a/indra/llcorehttp/httpcommon.cpp	Fri Sep 20 07:13:14 2013 +0000
     3.2 +++ b/indra/llcorehttp/httpcommon.cpp	Tue Sep 24 14:49:26 2013 -0400
     3.3 @@ -70,7 +70,8 @@
     3.4  			"Invalid datatype for argument or option",
     3.5  			"Option has not been explicitly set",
     3.6  			"Option is not dynamic and must be set early",
     3.7 -			"Invalid HTTP status code received from server"
     3.8 +			"Invalid HTTP status code received from server",
     3.9 +			"Could not allocate required resource"
    3.10  		};
    3.11  	static const int llcore_errors_count(sizeof(llcore_errors) / sizeof(llcore_errors[0]));
    3.12  
     4.1 --- a/indra/llcorehttp/httpcommon.h	Fri Sep 20 07:13:14 2013 +0000
     4.2 +++ b/indra/llcorehttp/httpcommon.h	Tue Sep 24 14:49:26 2013 -0400
     4.3 @@ -246,7 +246,10 @@
     4.4  	HE_OPT_NOT_DYNAMIC = 8,
     4.5  	
     4.6  	// Invalid HTTP status code returned by server
     4.7 -	HE_INVALID_HTTP_STATUS = 9
     4.8 +	HE_INVALID_HTTP_STATUS = 9,
     4.9 +	
    4.10 +	// Couldn't allocate resource, typically libcurl handle
    4.11 +	HE_BAD_ALLOC = 10
    4.12  	
    4.13  }; // end enum HttpError
    4.14  
     5.1 --- a/indra/llmessage/llcurl.cpp	Fri Sep 20 07:13:14 2013 +0000
     5.2 +++ b/indra/llmessage/llcurl.cpp	Tue Sep 24 14:49:26 2013 -0400
     5.3 @@ -6,7 +6,7 @@
     5.4   *
     5.5   * $LicenseInfo:firstyear=2006&license=viewerlgpl$
     5.6   * Second Life Viewer Source Code
     5.7 - * Copyright (C) 2010, Linden Research, Inc.
     5.8 + * Copyright (C) 2010-2013, Linden Research, Inc.
     5.9   * 
    5.10   * This library is free software; you can redistribute it and/or
    5.11   * modify it under the terms of the GNU Lesser General Public
    5.12 @@ -293,9 +293,12 @@
    5.13  		return NULL;
    5.14  	}
    5.15  	
    5.16 -	// set no DNS caching as default for all easy handles. This prevents them adopting a
    5.17 -	// multi handles cache if they are added to one.
    5.18 -	CURLcode result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
    5.19 +	// Enable a brief cache period for now.  This was zero for the longest time
    5.20 +	// which caused some routers grief and generated unneeded traffic.  For the
    5.21 +	// threded resolver, we're using system resolution libraries and non-zero values
    5.22 +	// are preferred.  The c-ares resolver is another matter and it might not
    5.23 +	// track server changes as well.
    5.24 +	CURLcode result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
    5.25  	check_curl_code(result);
    5.26  	result = curl_easy_setopt(easy->mCurlEasyHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
    5.27  	check_curl_code(result);
     6.1 --- a/indra/newview/llmeshrepository.cpp	Fri Sep 20 07:13:14 2013 +0000
     6.2 +++ b/indra/newview/llmeshrepository.cpp	Tue Sep 24 14:49:26 2013 -0400
     6.3 @@ -78,8 +78,6 @@
     6.4  #include "netdb.h"
     6.5  #endif
     6.6  
     6.7 -#include <queue>
     6.8 -
     6.9  
    6.10  // Purpose
    6.11  //
    6.12 @@ -235,8 +233,7 @@
    6.13  //     mUploadWaitList                 none            rw.main.none (upload thread accessing objects)
    6.14  //     mInventoryQ                     mMeshMutex [4]  rw.main.mMeshMutex, ro.main.none [5]
    6.15  //     mUploadErrorQ                   mMeshMutex      rw.main.mMeshMutex, rw.any.mMeshMutex
    6.16 -//     mGetMeshCapability              none            rw.main.none [0], ro.any.none
    6.17 -//     mGetMesh2Capability             none            rw.main.none [0], ro.any.none
    6.18 +//     mGetMeshVersion                 none            rw.main.none
    6.19  //
    6.20  //   LLMeshRepoThread:
    6.21  //
    6.22 @@ -255,6 +252,9 @@
    6.23  //     mUnavailableQ            mMutex        rw.repo.none [0], ro.main.none [5], rw.main.mMutex
    6.24  //     mLoadedQ                 mMutex        rw.repo.mMutex, ro.main.none [5], rw.main.mMutex
    6.25  //     mPendingLOD              mMutex        rw.repo.mMutex, rw.any.mMutex
    6.26 +//     mGetMeshCapability       mMutex        rw.main.mMutex, ro.repo.mMutex (was:  [0])
    6.27 +//     mGetMesh2Capability      mMutex        rw.main.mMutex, ro.repo.mMutex (was:  [0])
    6.28 +//     mGetMeshVersion          mMutex        rw.main.mMutex, ro.repo.mMutex
    6.29  //     mHttp*                   none          rw.repo.none
    6.30  //
    6.31  // QA/Development Testing
    6.32 @@ -304,7 +304,10 @@
    6.33  // With this instrumentation enabled, a stall will appear
    6.34  // under the 'Mesh Fetch' timer which will be either top-level
    6.35  // or under 'Render' time.
    6.36 +
    6.37 +#ifndef	LL_MESH_FASTTIMER_ENABLE
    6.38  #define LL_MESH_FASTTIMER_ENABLE		1
    6.39 +#endif
    6.40  #if LL_MESH_FASTTIMER_ENABLE
    6.41  static LLFastTimer::DeclareTimer FTM_MESH_FETCH("Mesh Fetch");
    6.42  
    6.43 @@ -381,7 +384,6 @@
    6.44  std::string make_dump_name(std::string prefix, S32 num)
    6.45  {
    6.46  	return prefix + boost::lexical_cast<std::string>(num) + std::string(".xml");
    6.47 -	
    6.48  }
    6.49  void dump_llsd_to_file(const LLSD& content, std::string filename);
    6.50  LLSD llsd_from_file(std::string filename);
    6.51 @@ -740,7 +742,8 @@
    6.52    mHttpPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
    6.53    mHttpLegacyPolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
    6.54    mHttpLargePolicyClass(LLCore::HttpRequest::DEFAULT_POLICY_ID),
    6.55 -  mHttpPriority(0)
    6.56 +  mHttpPriority(0),
    6.57 +  mGetMeshVersion(2)
    6.58  { 
    6.59  	mMutex = new LLMutex(NULL);
    6.60  	mHeaderMutex = new LLMutex(NULL);
    6.61 @@ -1047,30 +1050,50 @@
    6.62  	}
    6.63  }
    6.64  
    6.65 +// Mutex:  must be holding mMutex when called
    6.66 +void LLMeshRepoThread::setGetMeshCaps(const std::string & get_mesh1,
    6.67 +									  const std::string & get_mesh2,
    6.68 +									  int pref_version)
    6.69 +{
    6.70 +	mGetMeshCapability = get_mesh1;
    6.71 +	mGetMesh2Capability = get_mesh2;
    6.72 +	mGetMeshVersion = pref_version;
    6.73 +}
    6.74 +
    6.75 +
    6.76  // Constructs a Cap URL for the mesh.  Prefers a GetMesh2 cap
    6.77  // over a GetMesh cap.
    6.78  //
    6.79 -//static 
    6.80 -std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id)
    6.81 +// Mutex:  acquires mMutex
    6.82 +void LLMeshRepoThread::constructUrl(LLUUID mesh_id, std::string * url, int * version)
    6.83  {
    6.84 -	std::string http_url;
    6.85 +	std::string res_url;
    6.86 +	int res_version(2);
    6.87  	
    6.88  	if (gAgent.getRegion())
    6.89  	{
    6.90 -		if (! gMeshRepo.mGetMesh2Capability.empty() && gMeshRepo.mGetMeshVersion > 1)
    6.91 +		LLMutexLock lock(mMutex);
    6.92 +
    6.93 +		// Get a consistent pair of (cap string, version).  The
    6.94 +		// locking could be eliminated here without loss of safety
    6.95 +		// by using a set of staging values in setGetMeshCaps().
    6.96 +		
    6.97 +		if (! mGetMesh2Capability.empty() && mGetMeshVersion > 1)
    6.98  		{
    6.99 -			http_url = gMeshRepo.mGetMesh2Capability;
   6.100 +			res_url = mGetMesh2Capability;
   6.101 +			res_version = 2;
   6.102  		}
   6.103  		else
   6.104  		{
   6.105 -			http_url = gMeshRepo.mGetMeshCapability;
   6.106 +			res_url = mGetMeshCapability;
   6.107 +			res_version = 1;
   6.108  		}
   6.109  	}
   6.110  
   6.111 -	if (!http_url.empty())
   6.112 +	if (! res_url.empty())
   6.113  	{
   6.114 -		http_url += "/?mesh_id=";
   6.115 -		http_url += mesh_id.asString().c_str();
   6.116 +		res_url += "/?mesh_id=";
   6.117 +		res_url += mesh_id.asString().c_str();
   6.118  	}
   6.119  	else
   6.120  	{
   6.121 @@ -1078,7 +1101,8 @@
   6.122  								<< mesh_id << ".mesh" << LL_ENDL;
   6.123  	}
   6.124  
   6.125 -	return http_url;
   6.126 +	*url = res_url;
   6.127 +	*version = res_version;
   6.128  }
   6.129  
   6.130  // Issue an HTTP GET request with byte range using the right
   6.131 @@ -1200,8 +1224,10 @@
   6.132  			}
   6.133  
   6.134  			//reading from VFS failed for whatever reason, fetch from sim
   6.135 -			int cap_version(gMeshRepo.mGetMeshVersion);
   6.136 -			std::string http_url = constructUrl(mesh_id);
   6.137 +			int cap_version(2);
   6.138 +			std::string http_url;
   6.139 +			constructUrl(mesh_id, &http_url, &cap_version);
   6.140 +
   6.141  			if (!http_url.empty())
   6.142  			{
   6.143  				LLMeshSkinInfoHandler * handler = new LLMeshSkinInfoHandler(mesh_id, offset, size);
   6.144 @@ -1293,8 +1319,10 @@
   6.145  			}
   6.146  
   6.147  			//reading from VFS failed for whatever reason, fetch from sim
   6.148 -			int cap_version(gMeshRepo.mGetMeshVersion);
   6.149 -			std::string http_url = constructUrl(mesh_id);
   6.150 +			int cap_version(2);
   6.151 +			std::string http_url;
   6.152 +			constructUrl(mesh_id, &http_url, &cap_version);
   6.153 +			
   6.154  			if (!http_url.empty())
   6.155  			{
   6.156  				LLMeshDecompositionHandler * handler = new LLMeshDecompositionHandler(mesh_id, offset, size);
   6.157 @@ -1384,8 +1412,10 @@
   6.158  			}
   6.159  
   6.160  			//reading from VFS failed for whatever reason, fetch from sim
   6.161 -			int cap_version(gMeshRepo.mGetMeshVersion);
   6.162 -			std::string http_url = constructUrl(mesh_id);
   6.163 +			int cap_version(2);
   6.164 +			std::string http_url;
   6.165 +			constructUrl(mesh_id, &http_url, &cap_version);
   6.166 +			
   6.167  			if (!http_url.empty())
   6.168  			{
   6.169  				LLMeshPhysicsShapeHandler * handler = new LLMeshPhysicsShapeHandler(mesh_id, offset, size);
   6.170 @@ -1477,8 +1507,10 @@
   6.171  
   6.172  	//either cache entry doesn't exist or is corrupt, request header from simulator	
   6.173  	bool retval = true;
   6.174 -	int cap_version(gMeshRepo.mGetMeshVersion);
   6.175 -	std::string http_url = constructUrl(mesh_params.getSculptID());
   6.176 +	int cap_version(2);
   6.177 +	std::string http_url;
   6.178 +	constructUrl(mesh_params.getSculptID(), &http_url, &cap_version);
   6.179 +	
   6.180  	if (!http_url.empty())
   6.181  	{
   6.182  		//grab first 4KB if we're going to bother with a fetch.  Cache will prevent future fetches if a full mesh fits
   6.183 @@ -1563,8 +1595,10 @@
   6.184  			}
   6.185  
   6.186  			//reading from VFS failed for whatever reason, fetch from sim
   6.187 -			int cap_version(gMeshRepo.mGetMeshVersion);
   6.188 -			std::string http_url = constructUrl(mesh_id);
   6.189 +			int cap_version(2);
   6.190 +			std::string http_url;
   6.191 +			constructUrl(mesh_id, &http_url, &cap_version);
   6.192 +			
   6.193  			if (!http_url.empty())
   6.194  			{
   6.195  				LLMeshLODHandler * handler = new LLMeshLODHandler(mesh_params, lod, offset, size);
   6.196 @@ -1812,7 +1846,6 @@
   6.197  	return true;
   6.198  }
   6.199  
   6.200 -
   6.201  LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
   6.202  									   bool upload_skin, bool upload_joints, const std::string & upload_url, bool do_upload,
   6.203  									   LLHandle<LLWholeModelFeeObserver> fee_observer,
   6.204 @@ -3249,15 +3282,15 @@
   6.205  			
   6.206  			if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived())
   6.207  			{
   6.208 +				region_name = gAgent.getRegion()->getName();
   6.209  				const bool use_v1(gSavedSettings.getBOOL("MeshUseGetMesh1"));
   6.210 -
   6.211 -				region_name = gAgent.getRegion()->getName();
   6.212 -				mGetMeshCapability = gAgent.getRegion()->getCapability("GetMesh");
   6.213 -				mGetMesh2Capability = gAgent.getRegion()->getCapability("GetMesh2");
   6.214 -				mGetMeshVersion = (mGetMesh2Capability.empty() || use_v1) ? 1 : 2;
   6.215 +				const std::string mesh1(gAgent.getRegion()->getCapability("GetMesh"));
   6.216 +				const std::string mesh2(gAgent.getRegion()->getCapability("GetMesh2"));
   6.217 +				mGetMeshVersion = (mesh2.empty() || use_v1) ? 1 : 2;
   6.218 +				mThread->setGetMeshCaps(mesh1, mesh2, mGetMeshVersion);
   6.219  				LL_DEBUGS(LOG_MESH) << "Retrieving caps for region '" << region_name
   6.220 -									<< "', GetMesh2:  " << mGetMesh2Capability
   6.221 -									<< ", GetMesh:  " << mGetMeshCapability
   6.222 +									<< "', GetMesh2:  " << mesh2
   6.223 +									<< ", GetMesh:  " << mesh1
   6.224  									<< ", using version:  " << mGetMeshVersion
   6.225  									<< LL_ENDL;
   6.226  			}
     7.1 --- a/indra/newview/llmeshrepository.h	Fri Sep 20 07:13:14 2013 +0000
     7.2 +++ b/indra/newview/llmeshrepository.h	Tue Sep 24 14:49:26 2013 -0400
     7.3 @@ -333,7 +333,9 @@
     7.4  	typedef std::set<LLCore::HttpHandler *> http_request_set;
     7.5  	http_request_set					mHttpRequestSet;			// Outstanding HTTP requests
     7.6  
     7.7 -	static std::string constructUrl(LLUUID mesh_id);
     7.8 +	std::string mGetMeshCapability;
     7.9 +	std::string mGetMesh2Capability;
    7.10 +	int mGetMeshVersion;
    7.11  
    7.12  	LLMeshRepoThread();
    7.13  	~LLMeshRepoThread();
    7.14 @@ -376,6 +378,17 @@
    7.15  	static void incActiveHeaderRequests();
    7.16  	static void decActiveHeaderRequests();
    7.17  
    7.18 +	// Set the caps strings and preferred version for constructing
    7.19 +	// mesh fetch URLs.
    7.20 +	//
    7.21 +	// Mutex:  must be holding mMutex when called
    7.22 +	void setGetMeshCaps(const std::string & get_mesh1,
    7.23 +						const std::string & get_mesh2,
    7.24 +						int pref_version);
    7.25 +
    7.26 +	// Mutex:  acquires mMutex
    7.27 +	void constructUrl(LLUUID mesh_id, std::string * url, int * version);
    7.28 +
    7.29  private:
    7.30  	// Issue a GET request to a URL with 'Range' header using
    7.31  	// the correct policy class and other attributes.  If an invalid
    7.32 @@ -613,9 +626,7 @@
    7.33  	void uploadError(LLSD& args);
    7.34  	void updateInventory(inventory_data data);
    7.35  
    7.36 -	std::string mGetMeshCapability;
    7.37 -	std::string mGetMesh2Capability;
    7.38 -	int mGetMeshVersion;
    7.39 +	int mGetMeshVersion;		// Shadows value in LLMeshRepoThread
    7.40  };
    7.41  
    7.42  extern LLMeshRepository gMeshRepo;

mercurial