SH-4365 SH-4367 Conversion of mesh uploaders to llcorehttp.

Thu, 25 Jul 2013 18:36:08 -0400

author
Monty Brandenberg <monty@lindenlab.com>
date
Thu, 25 Jul 2013 18:36:08 -0400
changeset 40697
1909fb80b76f
parent 40696
589d6dbc8c66
child 40698
8daa5f3fcf2e

SH-4365 SH-4367 Conversion of mesh uploaders to llcorehttp.
With this checkin, legacy LLCurl is out of the mesh code.
Uploaders and responders are converted and functioning. Logging
has been cleaned up throughout the code to use the macro form
with tag/subtag capability. DEBUGS-level logging added for some
upload path milestones. Better error information flow from
failed responses to viewer alert boxes but I'd really, really
like to do better here. Mesh upload problems are completely
opaque as a user. Minor cleanups (removed dead members,
method signatures tidied, less data conversion). Could almost
call this complete, will likely have platform cleanups, however.

indra/newview/llmeshrepository.cpp file | annotate | diff | revisions
indra/newview/llmeshrepository.h file | annotate | diff | revisions
     1.1 --- a/indra/newview/llmeshrepository.cpp	Thu Jul 18 18:43:58 2013 -0400
     1.2 +++ b/indra/newview/llmeshrepository.cpp	Thu Jul 25 18:36:08 2013 -0400
     1.3 @@ -68,6 +68,7 @@
     1.4  #include "llviewerparcelmgr.h"
     1.5  #include "lluploadfloaterobservers.h"
     1.6  #include "bufferarray.h"
     1.7 +#include "bufferstream.h"
     1.8  
     1.9  #include "boost/lexical_cast.hpp"
    1.10  
    1.11 @@ -203,6 +204,7 @@
    1.12  //     mUnavailableQ            mMutex        rw.repo.none [0], ro.main.none [3], rw.main.mMutex
    1.13  //     mLoadedQ                 mMutex        rw.repo.mMutex, ro.main.none [3], rw.main.mMutex
    1.14  //     mPendingLOD              mMutex        rw.repo.mMutex, rw.any.mMutex
    1.15 +//     mHttp*                   none          rw.repo.none
    1.16  //
    1.17  //   LLPhysicsDecomp:
    1.18  //    
    1.19 @@ -210,7 +212,19 @@
    1.20  //     mCurRequest
    1.21  //     mCompletedQ
    1.22  //
    1.23 -
    1.24 +//
    1.25 +// QA/Development Testing
    1.26 +//
    1.27 +//   Debug variable 'MeshUploadFakeErrors' takes a mask of bits that will
    1.28 +//   simulate an error on fee query or upload.  Defined bits are:
    1.29 +//
    1.30 +//   0x01            Simulate application error on fee check reading
    1.31 +//                   response body from file "fake_upload_error.xml"
    1.32 +//   0x02            Same as 0x01 but for actual upload attempt.
    1.33 +//   0x04            Simulate a transport problem on fee check with a
    1.34 +//                   locally-generated 500 status.
    1.35 +//   0x08            As with 0x04 but for the upload operation.
    1.36 +//
    1.37  
    1.38  LLMeshRepository gMeshRepo;
    1.39  
    1.40 @@ -362,6 +376,14 @@
    1.41  // processFailure() methods to customize handling and
    1.42  // error messages.
    1.43  //
    1.44 +// LLCore::HttpHandler
    1.45 +//   LLMeshHandlerBase
    1.46 +//     LLMeshHeaderHandler
    1.47 +//     LLMeshLODHandler
    1.48 +//     LLMeshSkinInfoHandler
    1.49 +//     LLMeshDecompositionHandler
    1.50 +//     LLMeshPhysicsShapeHandler
    1.51 +
    1.52  class LLMeshHandlerBase : public LLCore::HttpHandler
    1.53  {
    1.54  public:
    1.55 @@ -534,28 +556,31 @@
    1.56  };
    1.57  
    1.58  
    1.59 -void log_upload_error(S32 status, const LLSD& content, std::string stage, std::string model_name)
    1.60 +void log_upload_error(LLCore::HttpStatus status, const LLSD& content,
    1.61 +					  const char * const stage, const std::string & model_name)
    1.62  {
    1.63  	// Add notification popup.
    1.64  	LLSD args;
    1.65 -	std::string message = content["error"]["message"];
    1.66 -	std::string identifier = content["error"]["identifier"];
    1.67 +	std::string message = content["error"]["message"].asString();
    1.68 +	std::string identifier = content["error"]["identifier"].asString();
    1.69  	args["MESSAGE"] = message;
    1.70  	args["IDENTIFIER"] = identifier;
    1.71  	args["LABEL"] = model_name;
    1.72  	gMeshRepo.uploadError(args);
    1.73  
    1.74  	// Log details.
    1.75 -	llwarns << "stage: " << stage << " http status: " << status << llendl;
    1.76 +	LL_WARNS(LOG_MESH) << "Error in stage:  " << stage
    1.77 +					   << ", Reason:  " << status.toString()
    1.78 +					   << " (" << status.toHex() << ")" << LL_ENDL;
    1.79  	if (content.has("error"))
    1.80  	{
    1.81  		const LLSD& err = content["error"];
    1.82 -		llwarns << "err: " << err << llendl;
    1.83 -		llwarns << "mesh upload failed, stage '" << stage
    1.84 -				<< "' error '" << err["error"].asString()
    1.85 -				<< "', message '" << err["message"].asString()
    1.86 -				<< "', id '" << err["identifier"].asString()
    1.87 -				<< "'" << llendl;
    1.88 +		LL_WARNS(LOG_MESH) << "error: " << err << LL_ENDL;
    1.89 +		LL_WARNS(LOG_MESH) << "  mesh upload failed, stage '" << stage
    1.90 +						   << "', error '" << err["error"].asString()
    1.91 +						   << "', message '" << err["message"].asString()
    1.92 +						   << "', id '" << err["identifier"].asString()
    1.93 +						   << "'" << LL_ENDL;
    1.94  		if (err.has("errors"))
    1.95  		{
    1.96  			S32 error_num = 0;
    1.97 @@ -565,13 +590,13 @@
    1.98  				 ++it)
    1.99  			{
   1.100  				const LLSD& err_entry = *it;
   1.101 -				llwarns << "error[" << error_num << "]:" << llendl;
   1.102 +				LL_WARNS(LOG_MESH) << "  error[" << error_num << "]:" << LL_ENDL;
   1.103  				for (LLSD::map_const_iterator map_it = err_entry.beginMap();
   1.104  					 map_it != err_entry.endMap();
   1.105  					 ++map_it)
   1.106  				{
   1.107 -					llwarns << "\t" << map_it->first << ": "
   1.108 -							<< map_it->second << llendl;
   1.109 +					LL_WARNS(LOG_MESH) << "    " << map_it->first << ":  "
   1.110 +									   << map_it->second << LL_ENDL;
   1.111  				}
   1.112  				error_num++;
   1.113  			}
   1.114 @@ -579,141 +604,10 @@
   1.115  	}
   1.116  	else
   1.117  	{
   1.118 -		llwarns << "bad mesh, no error information available" << llendl;
   1.119 +		LL_WARNS(LOG_MESH) << "Bad response to mesh request, no additional error information available." << LL_ENDL;
   1.120  	}
   1.121  }
   1.122  
   1.123 -class LLWholeModelFeeResponder: public LLCurl::Responder
   1.124 -{
   1.125 -	LLMeshUploadThread* mThread;
   1.126 -	LLSD mModelData;
   1.127 -	LLHandle<LLWholeModelFeeObserver> mObserverHandle;
   1.128 -public:
   1.129 -	LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelFeeObserver> observer_handle):
   1.130 -		mThread(thread),
   1.131 -		mModelData(model_data),
   1.132 -		mObserverHandle(observer_handle)
   1.133 -	{
   1.134 -		if (mThread)
   1.135 -		{
   1.136 -			mThread->startRequest();
   1.137 -		}
   1.138 -	}
   1.139 -
   1.140 -	~LLWholeModelFeeResponder()
   1.141 -	{
   1.142 -		if (mThread)
   1.143 -		{
   1.144 -			mThread->stopRequest();
   1.145 -		}
   1.146 -	}
   1.147 -
   1.148 -	virtual void completed(U32 status,
   1.149 -						   const std::string& reason,
   1.150 -						   const LLSD& content)
   1.151 -	{
   1.152 -		LLSD cc = content;
   1.153 -		if (gSavedSettings.getS32("MeshUploadFakeErrors")&1)
   1.154 -		{
   1.155 -			cc = llsd_from_file("fake_upload_error.xml");
   1.156 -		}
   1.157 -			
   1.158 -		dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num));
   1.159 -
   1.160 -		LLWholeModelFeeObserver* observer = mObserverHandle.get();
   1.161 -
   1.162 -		if (isGoodStatus(status) &&
   1.163 -			cc["state"].asString() == "upload")
   1.164 -		{
   1.165 -			mThread->mWholeModelUploadURL = cc["uploader"].asString();
   1.166 -
   1.167 -			if (observer)
   1.168 -			{
   1.169 -				cc["data"]["upload_price"] = cc["upload_price"];
   1.170 -				observer->onModelPhysicsFeeReceived(cc["data"], mThread->mWholeModelUploadURL);
   1.171 -			}
   1.172 -		}
   1.173 -		else
   1.174 -		{
   1.175 -			llwarns << "fee request failed" << llendl;
   1.176 -			log_upload_error(status,cc,"fee",mModelData["name"]);
   1.177 -			mThread->mWholeModelUploadURL = "";
   1.178 -
   1.179 -			if (observer)
   1.180 -			{
   1.181 -				observer->setModelPhysicsFeeErrorStatus(status, reason);
   1.182 -			}
   1.183 -		}
   1.184 -	}
   1.185 -
   1.186 -};
   1.187 -
   1.188 -class LLWholeModelUploadResponder: public LLCurl::Responder
   1.189 -{
   1.190 -	LLMeshUploadThread* mThread;
   1.191 -	LLSD mModelData;
   1.192 -	LLHandle<LLWholeModelUploadObserver> mObserverHandle;
   1.193 -	
   1.194 -public:
   1.195 -	LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelUploadObserver> observer_handle):
   1.196 -		mThread(thread),
   1.197 -		mModelData(model_data),
   1.198 -		mObserverHandle(observer_handle)
   1.199 -	{
   1.200 -		if (mThread)
   1.201 -		{
   1.202 -			mThread->startRequest();
   1.203 -		}
   1.204 -	}
   1.205 -
   1.206 -	~LLWholeModelUploadResponder()
   1.207 -	{
   1.208 -		if (mThread)
   1.209 -		{
   1.210 -			mThread->stopRequest();
   1.211 -		}
   1.212 -	}
   1.213 -
   1.214 -	virtual void completed(U32 status,
   1.215 -						   const std::string& reason,
   1.216 -						   const LLSD& content)
   1.217 -	{
   1.218 -		LLSD cc = content;
   1.219 -		if (gSavedSettings.getS32("MeshUploadFakeErrors")&2)
   1.220 -		{
   1.221 -			cc = llsd_from_file("fake_upload_error.xml");
   1.222 -		}
   1.223 -
   1.224 -		dump_llsd_to_file(cc,make_dump_name("whole_model_upload_response_",dump_num));
   1.225 -		
   1.226 -		LLWholeModelUploadObserver* observer = mObserverHandle.get();
   1.227 -
   1.228 -		// requested "mesh" asset type isn't actually the type
   1.229 -		// of the resultant object, fix it up here.
   1.230 -		if (isGoodStatus(status) &&
   1.231 -			cc["state"].asString() == "complete")
   1.232 -		{
   1.233 -			mModelData["asset_type"] = "object";
   1.234 -			gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mModelData,cc));
   1.235 -
   1.236 -			if (observer)
   1.237 -			{
   1.238 -				doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadSuccess, observer));
   1.239 -			}
   1.240 -		}
   1.241 -		else
   1.242 -		{
   1.243 -			llwarns << "upload failed" << llendl;
   1.244 -			std::string model_name = mModelData["name"].asString();
   1.245 -			log_upload_error(status,cc,"upload",model_name);
   1.246 -
   1.247 -			if (observer)
   1.248 -			{
   1.249 -				doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadFailure, observer));
   1.250 -			}
   1.251 -		}
   1.252 -	}
   1.253 -};
   1.254  
   1.255  LLMeshRepoThread::LLMeshRepoThread()
   1.256  : LLThread("mesh repo"),
   1.257 @@ -788,7 +682,7 @@
   1.258  	LLCDResult res = LLConvexDecomposition::initThread();
   1.259  	if (res != LLCD_OK)
   1.260  	{
   1.261 -		llwarns << "convex decomposition unable to be loaded" << llendl;
   1.262 +		LL_WARNS(LOG_MESH) << "Convex decomposition unable to be loaded.  Expect severe problems." << LL_ENDL;
   1.263  	}
   1.264  
   1.265  	while (!LLApp::isQuitting())
   1.266 @@ -923,7 +817,7 @@
   1.267  	res = LLConvexDecomposition::quitThread();
   1.268  	if (res != LLCD_OK)
   1.269  	{
   1.270 -		llwarns << "convex decomposition unable to be quit" << llendl;
   1.271 +		LL_WARNS(LOG_MESH) << "Convex decomposition unable to be quit." << LL_ENDL;
   1.272  	}
   1.273  }
   1.274  
   1.275 @@ -951,7 +845,6 @@
   1.276  }
   1.277  
   1.278  
   1.279 -
   1.280  void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
   1.281  { //could be called from any thread
   1.282  	LLMutexLock lock(mMutex);
   1.283 @@ -1648,7 +1541,7 @@
   1.284  		LLMeshSkinInfo info(skin);
   1.285  		info.mMeshID = mesh_id;
   1.286  
   1.287 -		//llinfos<<"info pelvis offset"<<info.mPelvisOffset<<llendl;
   1.288 +		// LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL;
   1.289  		mSkinInfoQ.push(info);
   1.290  	}
   1.291  
   1.292 @@ -1739,10 +1632,13 @@
   1.293  	return true;
   1.294  }
   1.295  
   1.296 +
   1.297  LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
   1.298 -										bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload,
   1.299 -					   LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)
   1.300 -: LLThread("mesh upload"),
   1.301 +									   bool upload_skin, bool upload_joints, const std::string & upload_url, bool do_upload,
   1.302 +									   LLHandle<LLWholeModelFeeObserver> fee_observer,
   1.303 +									   LLHandle<LLWholeModelUploadObserver> upload_observer)
   1.304 +  : LLThread("mesh upload"),
   1.305 +	LLCore::HttpHandler(),
   1.306  	mDiscarded(FALSE),
   1.307  	mDoUpload(do_upload),
   1.308  	mWholeModelUploadURL(upload_url),
   1.309 @@ -1754,7 +1650,6 @@
   1.310  	mUploadSkin = upload_skin;
   1.311  	mUploadJoints = upload_joints;
   1.312  	mMutex = new LLMutex(NULL);
   1.313 -	mCurlRequest = NULL;
   1.314  	mPendingUploads = 0;
   1.315  	mFinished = false;
   1.316  	mOrigin = gAgent.getPositionAgent();
   1.317 @@ -1764,12 +1659,31 @@
   1.318  
   1.319  	mOrigin += gAgent.getAtAxis() * scale.magVec();
   1.320  
   1.321 -	mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut") ;
   1.322 +	mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut");
   1.323 +
   1.324 +	mHttpRequest = new LLCore::HttpRequest;
   1.325 +	mHttpOptions = new LLCore::HttpOptions;
   1.326 +	mHttpOptions->setTransferTimeout(mMeshUploadTimeOut);
   1.327 +	mHttpHeaders = new LLCore::HttpHeaders;
   1.328 +	mHttpHeaders->append("Content-Type", "application/llsd+xml");
   1.329 +	mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_UPLOADS);
   1.330 +	mHttpPriority = 0;
   1.331  }
   1.332  
   1.333  LLMeshUploadThread::~LLMeshUploadThread()
   1.334  {
   1.335 -
   1.336 +	if (mHttpHeaders)
   1.337 +	{
   1.338 +		mHttpHeaders->release();
   1.339 +		mHttpHeaders = NULL;
   1.340 +	}
   1.341 +	if (mHttpOptions)
   1.342 +	{
   1.343 +		mHttpOptions->release();
   1.344 +		mHttpOptions = NULL;
   1.345 +	}
   1.346 +	delete mHttpRequest;
   1.347 +	mHttpRequest = NULL;
   1.348  }
   1.349  
   1.350  LLMeshUploadThread::DecompRequest::DecompRequest(LLModel* mdl, LLModel* base_model, LLMeshUploadThread* thread)
   1.351 @@ -1811,14 +1725,14 @@
   1.352  
   1.353  void LLMeshUploadThread::discard()
   1.354  {
   1.355 -	LLMutexLock lock(mMutex) ;
   1.356 -	mDiscarded = TRUE ;
   1.357 +	LLMutexLock lock(mMutex);
   1.358 +	mDiscarded = TRUE;
   1.359  }
   1.360  
   1.361 -BOOL LLMeshUploadThread::isDiscarded()
   1.362 +BOOL LLMeshUploadThread::isDiscarded() const
   1.363  {
   1.364 -	LLMutexLock lock(mMutex) ;
   1.365 -	return mDiscarded ;
   1.366 +	LLMutexLock lock(mMutex);
   1.367 +	return mDiscarded;
   1.368  }
   1.369  
   1.370  void LLMeshUploadThread::run()
   1.371 @@ -2069,7 +1983,7 @@
   1.372  		}
   1.373  	}
   1.374  		
   1.375 -	if(has_valid_requests)
   1.376 +	if (has_valid_requests)
   1.377  	{
   1.378  		while (!mPhysicsComplete)
   1.379  		{
   1.380 @@ -2080,7 +1994,7 @@
   1.381  
   1.382  void LLMeshUploadThread::doWholeModelUpload()
   1.383  {
   1.384 -	mCurlRequest = new LLCurlRequest();
   1.385 +	LL_DEBUGS(LOG_MESH) << "Starting model upload.  Instances:  " << mInstance.size() << LL_ENDL;
   1.386  
   1.387  	if (mWholeModelUploadURL.empty())
   1.388  	{
   1.389 @@ -2090,75 +2004,240 @@
   1.390  	else
   1.391  	{
   1.392  		generateHulls();
   1.393 -
   1.394 -		LLSD full_model_data;
   1.395 -		wholeModelToLLSD(full_model_data, true);
   1.396 -		LLSD body = full_model_data["asset_resources"];
   1.397 -		dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num));
   1.398 -		LLCurlRequest::headers_t headers;
   1.399 -
   1.400 +		LL_DEBUGS(LOG_MESH) << "Hull generation completed." << LL_ENDL;
   1.401 +
   1.402 +		mModelData = LLSD::emptyMap();
   1.403 +		wholeModelToLLSD(mModelData, true);
   1.404 +		LLSD body = mModelData["asset_resources"];
   1.405 +		dump_llsd_to_file(body, make_dump_name("whole_model_body_", dump_num));
   1.406 +
   1.407 +		LLCore::BufferArray * ba = new LLCore::BufferArray;
   1.408 +		LLCore::BufferArrayStream bas(ba);
   1.409 +		LLSDSerialize::toXML(body, bas);
   1.410 +		// LLSDSerialize::toXML(mModelData, bas);		// <- This will generate a convenient upload error
   1.411 +		LLCore::HttpHandle handle = mHttpRequest->requestPost(mHttpPolicyClass,
   1.412 +															  mHttpPriority,
   1.413 +															  mWholeModelUploadURL,
   1.414 +															  ba,
   1.415 +															  mHttpOptions,
   1.416 +															  mHttpHeaders,
   1.417 +															  this);
   1.418 +		ba->release();
   1.419 +		
   1.420 +		if (LLCORE_HTTP_HANDLE_INVALID == handle)
   1.421  		{
   1.422 -			LLCurl::ResponderPtr responder = new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle) ;
   1.423 -
   1.424 -			while(!mCurlRequest->post(mWholeModelUploadURL, headers, body, responder, mMeshUploadTimeOut))
   1.425 +			mHttpStatus = mHttpRequest->getStatus();
   1.426 +		
   1.427 +			LL_WARNS(LOG_MESH) << "Couldn't issue request for full model upload.  Reason:  " << mHttpStatus.toString()
   1.428 +							   << " (" << mHttpStatus.toHex() << ")"
   1.429 +							   << LL_ENDL;
   1.430 +		}
   1.431 +		else
   1.432 +		{
   1.433 +			U32 sleep_time(10);
   1.434 +		
   1.435 +			LL_DEBUGS(LOG_MESH) << "POST request issued." << LL_ENDL;
   1.436 +			
   1.437 +			mHttpRequest->update(0);
   1.438 +			while (! LLApp::isQuitting() && ! mFinished)
   1.439  			{
   1.440 -				//sleep for 10ms to prevent eating a whole core
   1.441 -				apr_sleep(10000);
   1.442 +				ms_sleep(sleep_time);
   1.443 +				sleep_time = llmin(250U, sleep_time + sleep_time);
   1.444 +				mHttpRequest->update(0);
   1.445  			}
   1.446 +			LL_DEBUGS(LOG_MESH) << "Mesh upload operation completed." << LL_ENDL;
   1.447  		}
   1.448 -
   1.449 -		do
   1.450 -		{
   1.451 -			mCurlRequest->process();
   1.452 -			//sleep for 10ms to prevent eating a whole core
   1.453 -			apr_sleep(10000);
   1.454 -		} while (!LLAppViewer::isQuitting() && mPendingUploads > 0);
   1.455  	}
   1.456 -
   1.457 -	delete mCurlRequest;
   1.458 -	mCurlRequest = NULL;
   1.459 -
   1.460 -	// Currently a no-op.
   1.461 -	mFinished = true;
   1.462  }
   1.463  
   1.464  void LLMeshUploadThread::requestWholeModelFee()
   1.465  {
   1.466  	dump_num++;
   1.467  
   1.468 -	mCurlRequest = new LLCurlRequest();
   1.469 -
   1.470  	generateHulls();
   1.471  
   1.472 -	LLSD model_data;
   1.473 -	wholeModelToLLSD(model_data,false);
   1.474 -	dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num));
   1.475 -
   1.476 -	LLCurlRequest::headers_t headers;
   1.477 -
   1.478 +	mModelData = LLSD::emptyMap();
   1.479 +	wholeModelToLLSD(mModelData, false);
   1.480 +	dump_llsd_to_file(mModelData, make_dump_name("whole_model_fee_request_", dump_num));
   1.481 +
   1.482 +	LLCore::BufferArray * ba = new LLCore::BufferArray;
   1.483 +	LLCore::BufferArrayStream bas(ba);
   1.484 +	LLSDSerialize::toXML(mModelData, bas);
   1.485 +		
   1.486 +	LLCore::HttpHandle handle = mHttpRequest->requestPost(mHttpPolicyClass,
   1.487 +														  mHttpPriority,
   1.488 +														  mWholeModelFeeCapability,
   1.489 +														  ba,
   1.490 +														  mHttpOptions,
   1.491 +														  mHttpHeaders,
   1.492 +														  this);
   1.493 +	ba->release();
   1.494 +	if (LLCORE_HTTP_HANDLE_INVALID == handle)
   1.495  	{
   1.496 -		LLCurl::ResponderPtr responder = new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle) ;
   1.497 -		while(!mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, responder, mMeshUploadTimeOut))
   1.498 +		mHttpStatus = mHttpRequest->getStatus();
   1.499 +		
   1.500 +		LL_WARNS(LOG_MESH) << "Couldn't issue request for model fee.  Reason:  " << mHttpStatus.toString()
   1.501 +						   << " (" << mHttpStatus.toHex() << ")"
   1.502 +						   << LL_ENDL;
   1.503 +	}
   1.504 +	else
   1.505 +	{
   1.506 +		U32 sleep_time(10);
   1.507 +		
   1.508 +		mHttpRequest->update(0);
   1.509 +		while (! LLApp::isQuitting() && ! mFinished)
   1.510  		{
   1.511 -			//sleep for 10ms to prevent eating a whole core
   1.512 -			apr_sleep(10000);
   1.513 +			ms_sleep(sleep_time);
   1.514 +			sleep_time = llmin(250U, sleep_time + sleep_time);
   1.515 +			mHttpRequest->update(0);
   1.516  		}
   1.517  	}
   1.518 -
   1.519 -	do
   1.520 +}
   1.521 +
   1.522 +
   1.523 +// Does completion duty for both fee queries and actual uploads.
   1.524 +void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
   1.525 +{
   1.526 +	// QA/Devel:  0x2 to enable fake error import on upload, 0x1 on fee check
   1.527 +	const S32 fake_error(gSavedSettings.getS32("MeshUploadFakeErrors") & (mDoUpload ? 0xa : 0x5));
   1.528 +	LLCore::HttpStatus status(response->getStatus());
   1.529 +	if (fake_error)
   1.530  	{
   1.531 -		mCurlRequest->process();
   1.532 -		//sleep for 10ms to prevent eating a whole core
   1.533 -		apr_sleep(10000);
   1.534 -	} while (!LLApp::isQuitting() && mPendingUploads > 0);
   1.535 -
   1.536 -	delete mCurlRequest;
   1.537 -	mCurlRequest = NULL;
   1.538 -
   1.539 -	// Currently a no-op.
   1.540 +		status = (fake_error & 0x0c) ? LLCore::HttpStatus(500) : LLCore::HttpStatus(200);
   1.541 +	}
   1.542 +	std::string reason(status.toString());
   1.543 +	LLSD body;
   1.544 +
   1.545  	mFinished = true;
   1.546 +
   1.547 +	if (mDoUpload)
   1.548 +	{
   1.549 +		// model upload case
   1.550 +		LLWholeModelUploadObserver * observer(mUploadObserverHandle.get());
   1.551 +
   1.552 +		if (! status)
   1.553 +		{
   1.554 +			LL_WARNS(LOG_MESH) << "Upload failed.  Reason:  " << reason
   1.555 +							   << " (" << status.toHex() << ")"
   1.556 +							   << LL_ENDL;
   1.557 +
   1.558 +			// Build a fake body for the alert generator
   1.559 +			body["error"] = LLSD::emptyMap();
   1.560 +			body["error"]["message"] = reason;
   1.561 +			body["error"]["identifier"] = "NetworkError";		// from asset-upload/upload_util.py
   1.562 +			log_upload_error(status, body, "upload", mModelData["name"].asString());
   1.563 +
   1.564 +			if (observer)
   1.565 +			{
   1.566 +				doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadFailure, observer));
   1.567 +			}
   1.568 +		}
   1.569 +		else
   1.570 +		{
   1.571 +			if (fake_error & 0x2)
   1.572 +			{
   1.573 +				body = llsd_from_file("fake_upload_error.xml");
   1.574 +			}
   1.575 +			else
   1.576 +			{
   1.577 +				LLCore::BufferArray * ba(response->getBody());
   1.578 +				if (ba && ba->size())
   1.579 +				{
   1.580 +					LLCore::BufferArrayStream bas(ba);
   1.581 +					LLSDSerialize::fromXML(body, bas);
   1.582 +				}
   1.583 +			}
   1.584 +			dump_llsd_to_file(body, make_dump_name("whole_model_upload_response_", dump_num));
   1.585 +
   1.586 +			if (body["state"].asString() == "complete")
   1.587 +			{
   1.588 +				// requested "mesh" asset type isn't actually the type
   1.589 +				// of the resultant object, fix it up here.
   1.590 +				mModelData["asset_type"] = "object";
   1.591 +				gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mModelData, body));
   1.592 +
   1.593 +				if (observer)
   1.594 +				{
   1.595 +					doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadSuccess, observer));
   1.596 +				}
   1.597 +			}
   1.598 +			else
   1.599 +			{
   1.600 +				LL_WARNS(LOG_MESH) << "Upload failed.  Not in expected 'complete' state." << LL_ENDL;
   1.601 +				log_upload_error(status, body, "upload", mModelData["name"].asString());
   1.602 +
   1.603 +				if (observer)
   1.604 +				{
   1.605 +					doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadFailure, observer));
   1.606 +				}
   1.607 +			}
   1.608 +		}
   1.609 +	}
   1.610 +	else
   1.611 +	{
   1.612 +		// model fee case
   1.613 +		LLWholeModelFeeObserver* observer(mFeeObserverHandle.get());
   1.614 +		mWholeModelUploadURL.clear();
   1.615 +		
   1.616 +		if (! status)
   1.617 +		{
   1.618 +			LL_WARNS(LOG_MESH) << "Fee request failed.  Reason:  " << reason
   1.619 +							   << " (" << status.toHex() << ")"
   1.620 +							   << LL_ENDL;
   1.621 +
   1.622 +			// Build a fake body for the alert generator
   1.623 +			body["error"] = LLSD::emptyMap();
   1.624 +			body["error"]["message"] = reason;
   1.625 +			body["error"]["identifier"] = "NetworkError";		// from asset-upload/upload_util.py
   1.626 +			log_upload_error(status, body, "fee", mModelData["name"].asString());
   1.627 +
   1.628 +			if (observer)
   1.629 +			{
   1.630 +				observer->setModelPhysicsFeeErrorStatus(status.toULong(), reason);
   1.631 +			}
   1.632 +		}
   1.633 +		else
   1.634 +		{
   1.635 +			if (fake_error & 0x1)
   1.636 +			{
   1.637 +				body = llsd_from_file("fake_upload_error.xml");
   1.638 +			}
   1.639 +			else
   1.640 +			{
   1.641 +				LLCore::BufferArray * ba(response->getBody());
   1.642 +				if (ba && ba->size())
   1.643 +				{
   1.644 +					LLCore::BufferArrayStream bas(ba);
   1.645 +					LLSDSerialize::fromXML(body, bas);
   1.646 +				}
   1.647 +			}
   1.648 +			dump_llsd_to_file(body, make_dump_name("whole_model_fee_response_", dump_num));
   1.649 +		
   1.650 +			if (body["state"].asString() == "upload")
   1.651 +			{
   1.652 +				mWholeModelUploadURL = body["uploader"].asString();
   1.653 +
   1.654 +				if (observer)
   1.655 +				{
   1.656 +					body["data"]["upload_price"] = body["upload_price"];
   1.657 +					observer->onModelPhysicsFeeReceived(body["data"], mWholeModelUploadURL);
   1.658 +				}
   1.659 +			}
   1.660 +			else
   1.661 +			{
   1.662 +				LL_WARNS(LOG_MESH) << "Fee request failed.  Not in expected 'upload' state." << LL_ENDL;
   1.663 +				log_upload_error(status, body, "fee", mModelData["name"].asString());
   1.664 +
   1.665 +				if (observer)
   1.666 +				{
   1.667 +					observer->setModelPhysicsFeeErrorStatus(status.toULong(), reason);
   1.668 +				}
   1.669 +			}
   1.670 +		}
   1.671 +	}
   1.672  }
   1.673  
   1.674 +
   1.675  void LLMeshRepoThread::notifyLoadedMeshes()
   1.676  {
   1.677  	if (!mMutex)
   1.678 @@ -2674,13 +2753,13 @@
   1.679  
   1.680  void LLMeshRepository::shutdown()
   1.681  {
   1.682 -	llinfos << "Shutting down mesh repository." << llendl;
   1.683 +	LL_INFOS(LOG_MESH) << "Shutting down mesh repository." << LL_ENDL;
   1.684  
   1.685  	metrics_teleport_started_signal.disconnect();
   1.686  
   1.687  	for (U32 i = 0; i < mUploads.size(); ++i)
   1.688  	{
   1.689 -		llinfos << "Discard the pending mesh uploads " << llendl;
   1.690 +		LL_INFOS(LOG_MESH) << "Discard the pending mesh uploads." << LL_ENDL;
   1.691  		mUploads[i]->discard() ; //discard the uploading requests.
   1.692  	}
   1.693  
   1.694 @@ -2695,7 +2774,7 @@
   1.695  
   1.696  	for (U32 i = 0; i < mUploads.size(); ++i)
   1.697  	{
   1.698 -		llinfos << "Waiting for pending mesh upload " << i << "/" << mUploads.size() << llendl;
   1.699 +		LL_INFOS(LOG_MESH) << "Waiting for pending mesh upload " << i << "/" << mUploads.size() << LL_ENDL;
   1.700  		while (!mUploads[i]->isStopped())
   1.701  		{
   1.702  			apr_sleep(10);
   1.703 @@ -2708,7 +2787,7 @@
   1.704  	delete mMeshMutex;
   1.705  	mMeshMutex = NULL;
   1.706  
   1.707 -	llinfos << "Shutting down decomposition system." << llendl;
   1.708 +	LL_INFOS(LOG_MESH) << "Shutting down decomposition system." << LL_ENDL;
   1.709  
   1.710  	if (mDecompThread)
   1.711  	{
   1.712 @@ -3591,7 +3670,7 @@
   1.713  
   1.714  		if (ret)
   1.715  		{
   1.716 -			llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
   1.717 +			LL_ERRS(LOG_MESH) << "Convex Decomposition thread valid but could not set mesh data." << LL_ENDL;
   1.718  		}
   1.719  	}
   1.720  }
   1.721 @@ -3667,7 +3746,8 @@
   1.722  
   1.723  	if (ret)
   1.724  	{
   1.725 -		llwarns << "Convex Decomposition thread valid but could not execute stage " << stage << llendl;
   1.726 +		LL_WARNS(LOG_MESH) << "Convex Decomposition thread valid but could not execute stage " << stage << "."
   1.727 +						   << LL_ENDL;
   1.728  		LLMutexLock lock(mMutex);
   1.729  
   1.730  		mCurRequest->mHull.clear();
   1.731 @@ -3796,9 +3876,9 @@
   1.732  	setMeshData(mesh, true);
   1.733  
   1.734  	LLCDResult ret = decomp->buildSingleHull() ;
   1.735 -	if(ret)
   1.736 +	if (ret)
   1.737  	{
   1.738 -		llwarns << "Could not execute decomposition stage when attempting to create single hull." << llendl;
   1.739 +		LL_WARNS(LOG_MESH) << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL;
   1.740  		make_box(mCurRequest);
   1.741  	}
   1.742  	else
   1.743 @@ -4152,7 +4232,7 @@
   1.744  		metrics["teleports"] = LLSD::Integer(metrics_teleport_start_count);
   1.745  		metrics["user_cpu"] = double(user_cpu) / 1.0e6;
   1.746  		metrics["sys_cpu"] = double(sys_cpu) / 1.0e6;
   1.747 -		llinfos << "EventMarker " << metrics << llendl;
   1.748 +		LL_INFOS(LOG_MESH) << "EventMarker " << metrics << LL_ENDL;
   1.749  	}
   1.750  }
   1.751  
     2.1 --- a/indra/newview/llmeshrepository.h	Thu Jul 18 18:43:58 2013 -0400
     2.2 +++ b/indra/newview/llmeshrepository.h	Thu Jul 25 18:36:08 2013 -0400
     2.3 @@ -45,8 +45,6 @@
     2.4  #include "lluploadfloaterobservers.h"
     2.5  
     2.6  class LLVOVolume;
     2.7 -class LLMeshResponder;
     2.8 -class LLCurlRequest;
     2.9  class LLMutex;
    2.10  class LLCondition;
    2.11  class LLVFS;
    2.12 @@ -396,7 +394,14 @@
    2.13  	U32 mHttpLargeGetCount;
    2.14  };
    2.15  
    2.16 -class LLMeshUploadThread : public LLThread 
    2.17 +
    2.18 +// Class whose instances represent a single upload-type request for
    2.19 +// meshes:  one fee query or one actual upload attempt.  Yes, it creates
    2.20 +// a unique thread for that single request.  As it is 1:1, it can also
    2.21 +// trivially serve as the HttpHandler object for request completion
    2.22 +// notifications.
    2.23 +
    2.24 +class LLMeshUploadThread : public LLThread, public LLCore::HttpHandler 
    2.25  {
    2.26  private:
    2.27  	S32 mMeshUploadTimeOut ; //maximum time in seconds to execute an uploading request.
    2.28 @@ -417,44 +422,41 @@
    2.29  	};
    2.30  
    2.31  	LLPointer<DecompRequest> mFinalDecomp;
    2.32 -	bool mPhysicsComplete;
    2.33 +	volatile bool	mPhysicsComplete;
    2.34  
    2.35  	typedef std::map<LLPointer<LLModel>, std::vector<LLVector3> > hull_map;
    2.36 -	hull_map mHullMap;
    2.37 +	hull_map		mHullMap;
    2.38  
    2.39  	typedef std::vector<LLModelInstance> instance_list;
    2.40 -	instance_list mInstanceList;
    2.41 +	instance_list	mInstanceList;
    2.42  
    2.43  	typedef std::map<LLPointer<LLModel>, instance_list> instance_map;
    2.44 -	instance_map mInstance;
    2.45 +	instance_map	mInstance;
    2.46  
    2.47 -	LLMutex*					mMutex;
    2.48 -	LLCurlRequest* mCurlRequest;
    2.49 +	LLMutex*		mMutex;
    2.50  	S32				mPendingUploads;
    2.51  	LLVector3		mOrigin;
    2.52  	bool			mFinished;	
    2.53  	bool			mUploadTextures;
    2.54  	bool			mUploadSkin;
    2.55  	bool			mUploadJoints;
    2.56 -	BOOL            mDiscarded ;
    2.57 +	BOOL            mDiscarded;
    2.58  
    2.59  	LLHost			mHost;
    2.60  	std::string		mWholeModelFeeCapability;
    2.61  	std::string		mWholeModelUploadURL;
    2.62  
    2.63  	LLMeshUploadThread(instance_list& data, LLVector3& scale, bool upload_textures,
    2.64 -			bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true,
    2.65 -					   LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()), LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
    2.66 +					   bool upload_skin, bool upload_joints, const std::string & upload_url, bool do_upload = true,
    2.67 +					   LLHandle<LLWholeModelFeeObserver> fee_observer = (LLHandle<LLWholeModelFeeObserver>()),
    2.68 +					   LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
    2.69  	~LLMeshUploadThread();
    2.70  
    2.71 -	void startRequest() { ++mPendingUploads; }
    2.72 -	void stopRequest() { --mPendingUploads; }
    2.73 -		
    2.74 -	bool finished() { return mFinished; }
    2.75 +	bool finished() const { return mFinished; }
    2.76  	virtual void run();
    2.77  	void preStart();
    2.78  	void discard() ;
    2.79 -	BOOL isDiscarded();
    2.80 +	BOOL isDiscarded() const;
    2.81  
    2.82  	void generateHulls();
    2.83  
    2.84 @@ -471,11 +473,23 @@
    2.85  	void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; }
    2.86  	void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; }
    2.87  
    2.88 +	// Inherited from LLCore::HttpHandler
    2.89 +	virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
    2.90 +
    2.91  private:
    2.92  	LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
    2.93  	LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
    2.94  
    2.95  	bool mDoUpload; // if FALSE only model data will be requested, otherwise the model will be uploaded
    2.96 +	LLSD mModelData;
    2.97 +	
    2.98 +	// llcorehttp library interface objects.
    2.99 +	LLCore::HttpStatus					mHttpStatus;
   2.100 +	LLCore::HttpRequest *				mHttpRequest;
   2.101 +	LLCore::HttpOptions *				mHttpOptions;
   2.102 +	LLCore::HttpHeaders *				mHttpHeaders;
   2.103 +	LLCore::HttpRequest::policy_t		mHttpPolicyClass;
   2.104 +	LLCore::HttpRequest::priority_t		mHttpPriority;
   2.105  };
   2.106  
   2.107  class LLMeshRepository

mercurial