Commits

Monty Brandenberg  committed 2cbd624

SH-3189 Remove/improve naive data structures
When releasing HTTP waiters, avoid unnecessary sort activity.
For Content-Type in responses, let libcurl do the work and removed
my parsing of headers. Drop Content-Encoding as libcurl will deal
with that. If anyone is interested, they can parse.

  • Participants
  • Parent commits 50f4ce0

Comments (0)

Files changed (8)

File indra/llcorehttp/_httplibcurl.cpp

 		int http_status(HTTP_OK);
 
 		curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_status);
-		op->mStatus = LLCore::HttpStatus(http_status);
+		if (http_status >= 100 && http_status <= 999)
+		{
+			char * cont_type(NULL);
+			curl_easy_getinfo(handle, CURLINFO_CONTENT_TYPE, &cont_type);
+			if (cont_type)
+			{
+				op->mReplyConType = cont_type;
+			}
+			op->mStatus = HttpStatus(http_status);
+		}
+		else
+		{
+			LL_WARNS("CoreHttp") << "Invalid HTTP response code ("
+								 << http_status << ") received from server."
+								 << LL_ENDL;
+			op->mStatus = HttpStatus(HttpStatus::LLCORE, HE_INVALID_HTTP_STATUS);
+		}
 	}
 
 	// Detach from multi and recycle handle

File indra/llcorehttp/_httpoprequest.cpp

 			// Got an explicit offset/length in response
 			response->setRange(mReplyOffset, mReplyLength, mReplyFullLength);
 		}
-		response->setContent(mReplyConType, mReplyConEncode);
+		response->setContentType(mReplyConType);
 		
 		mUserHandler->onCompleted(static_cast<HttpHandle>(this), response);
 
 								HttpOptions * options,
 								HttpHeaders * headers)
 {
-	mProcFlags = PF_SCAN_CONTENT_HEADERS;		// Always scan for content headers
+	mProcFlags = 0U;
 	mReqPolicy = policy_id;
 	mReqPriority = priority;
 	mReqURL = url;
 		mReplyHeaders = NULL;
 	}
 	mReplyConType.clear();
-	mReplyConEncode.clear();
 	
 	// *FIXME:  better error handling later
 	HttpStatus status;
 	}
 	curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mCurlHeaders);
 
-	if (mProcFlags & (PF_SCAN_RANGE_HEADER | PF_SAVE_HEADERS | PF_SCAN_CONTENT_HEADERS))
+	if (mProcFlags & (PF_SCAN_RANGE_HEADER | PF_SAVE_HEADERS))
 	{
 		curl_easy_setopt(mCurlHandle, CURLOPT_HEADERFUNCTION, headerCallback);
 		curl_easy_setopt(mCurlHandle, CURLOPT_HEADERDATA, this);
 		op->mReplyOffset = 0;
 		op->mReplyLength = 0;
 		op->mReplyFullLength = 0;
-		op->mReplyConType.clear();
-		op->mReplyConEncode.clear();
 		op->mStatus = HttpStatus();
 		if (op->mReplyHeaders)
 		{
 		}
 	}
 
-	// Detect and parse 'Content-Type' and 'Content-Encoding' headers
-	if (op->mProcFlags & PF_SCAN_CONTENT_HEADERS)
-	{
-		if (wanted_hdr_size > con_type_line_len &&
-			! os_strncasecmp(hdr_data, con_type_line, con_type_line_len))
-		{
-			// Found 'Content-Type:', extract single-token value
-			std::string rhs(hdr_data + con_type_line_len, wanted_hdr_size - con_type_line_len);
-			std::string::size_type begin(0), end(rhs.size()), pos;
-
-			if ((pos = rhs.find_first_not_of(hdr_whitespace)) != std::string::npos)
-			{
-				begin = pos;
-			}
-			if ((pos = rhs.find_first_of(hdr_whitespace, begin)) != std::string::npos)
-			{
-				end = pos;
-			}
-			op->mReplyConType.assign(rhs, begin, end - begin);
-		}
-		else if (wanted_hdr_size > con_enc_line_len &&
-				 ! os_strncasecmp(hdr_data, con_enc_line, con_enc_line_len))
-		{
-			// Found 'Content-Encoding:', extract single-token value
-			std::string rhs(hdr_data + con_enc_line_len, wanted_hdr_size - con_enc_line_len);
-			std::string::size_type begin(0), end(rhs.size()), pos;
-
-			if ((pos = rhs.find_first_not_of(hdr_whitespace)) != std::string::npos)
-			{
-				begin = pos;
-			}
-			if ((pos = rhs.find_first_of(hdr_whitespace, begin)) != std::string::npos)
-			{
-				end = pos;
-			}
-			op->mReplyConEncode.assign(rhs, begin, end - begin);
-		}
-	}
-
 	return hdr_size;
 }
 

File indra/llcorehttp/_httpoprequest.h

 	unsigned int		mProcFlags;
 	static const unsigned int	PF_SCAN_RANGE_HEADER = 0x00000001U;
 	static const unsigned int	PF_SAVE_HEADERS = 0x00000002U;
-	static const unsigned int	PF_SCAN_CONTENT_HEADERS = 0x00000004U;
 
 public:
 	// Request data
 	size_t				mReplyFullLength;
 	HttpHeaders *		mReplyHeaders;
 	std::string			mReplyConType;
-	std::string			mReplyConEncode;
 
 	// Policy data
 	int					mPolicyRetries;

File indra/llcorehttp/httpcommon.cpp

 			"Request handle not found",
 			"Invalid datatype for argument or option",
 			"Option has not been explicitly set",
-			"Option is not dynamic and must be set early"
+			"Option is not dynamic and must be set early",
+			"Invalid HTTP status code received from server"
 		};
 	static const int llcore_errors_count(sizeof(llcore_errors) / sizeof(llcore_errors[0]));
 

File indra/llcorehttp/httpcommon.h

 	HE_OPT_NOT_SET = 7,
 	
 	// Option not dynamic, must be set during init phase
-	HE_OPT_NOT_DYNAMIC = 8
+	HE_OPT_NOT_DYNAMIC = 8,
+	
+	// Invalid HTTP status code returned by server
+	HE_INVALID_HTTP_STATUS = 9
 	
 }; // end enum HttpError
 

File indra/llcorehttp/httpresponse.h

 		}
 
 	///
-	void getContent(std::string & con_type, std::string & con_encode) const
+	const std::string & getContentType() const
 		{
-			con_type = mContentType;
-			con_encode = mContentEncoding;
+			return mContentType;
 		}
 
-	void setContent(const std::string & con_type, const std::string & con_encode)
+	void setContentType(const std::string & con_type)
 		{
 			mContentType = con_type;
-			mContentEncoding = con_encode;
 		}
 
 protected:
 	BufferArray *		mBufferArray;
 	HttpHeaders *		mHeaders;
 	std::string			mContentType;
-	std::string			mContentEncoding;
 };
 
 

File indra/llcorehttp/tests/test_httprequest.hpp

 			if (! mCheckContentType.empty())
 			{
 				ensure("Response required with content type check", response != NULL);
-				std::string con_type, con_enc;
-				response->getContent(con_type, con_enc);
+				std::string con_type(response->getContentType());
 				ensure("Content-Type as expected (" + mCheckContentType + ")",
 					   mCheckContentType == con_type);
 			}

File indra/newview/lltexturefetch.cpp

 	mNetworkQueueMutex.unlock();										// -Mfnq
 }
 
+// Release as many requests as permitted from the WAIT_HTTP_RESOURCE2
+// state to the SEND_HTTP_REQ state based on their current priority.
+//
+// This data structures and code associated with this looks a bit
+// indirect and naive but it's done in the name of safety.  An
+// ordered container may become invalid from time to time due to
+// priority changes caused by actions in other threads.  State itself
+// could also suffer the same fate with canceled operations.  Even
+// done this way, I'm not fully trusting we're truly safe.  This
+// module is due for a major refactoring and we'll deal with it then.
+//
 // Threads:  Ttf
 // Locks:  -Mw (must not hold any worker when called)
 void LLTextureFetch::releaseHttpWaiters()
 			tids2.push_back(worker);
 		}
 	}
-
-	// Sort into priority order
-	LLTextureFetchWorker::Compare compare;
-	std::sort(tids2.begin(), tids2.end(), compare);
 	tids.clear();
 
+	// Sort into priority order, if necessary and only as much as needed
+	if (tids2.size() > mHttpSemaphore)
+	{
+		LLTextureFetchWorker::Compare compare;
+		std::partial_sort(tids2.begin(), tids2.begin() + mHttpSemaphore, tids2.end(), compare);
+	}
+
 	// Release workers up to the high water mark.  Since we aren't
 	// holding any locks at this point, we can be in competition
 	// with other callers.  Do defensive things like getting