summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty Brandenberg <monty@lindenlab.com>2013-07-25 18:36:08 -0400
committerMonty Brandenberg <monty@lindenlab.com>2013-07-25 18:36:08 -0400
commitb7f14a7b39610ac1cb6db5fafeab568aa9b662c5 (patch)
tree147925dca4c5a75a929c50e6424e2531b37ba01d
parent38b3da4a20a0a06396d240a5e8fdc4fa11866937 (diff)
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.
-rwxr-xr-xindra/newview/llmeshrepository.cpp514
-rwxr-xr-xindra/newview/llmeshrepository.h48
2 files changed, 328 insertions, 234 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 2d003dd6d7..1f40026e80 100755
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -68,6 +68,7 @@
#include "llviewerparcelmgr.h"
#include "lluploadfloaterobservers.h"
#include "bufferarray.h"
+#include "bufferstream.h"
#include "boost/lexical_cast.hpp"
@@ -203,6 +204,7 @@
// mUnavailableQ mMutex rw.repo.none [0], ro.main.none [3], rw.main.mMutex
// mLoadedQ mMutex rw.repo.mMutex, ro.main.none [3], rw.main.mMutex
// mPendingLOD mMutex rw.repo.mMutex, rw.any.mMutex
+// mHttp* none rw.repo.none
//
// LLPhysicsDecomp:
//
@@ -210,7 +212,19 @@
// mCurRequest
// mCompletedQ
//
-
+//
+// QA/Development Testing
+//
+// Debug variable 'MeshUploadFakeErrors' takes a mask of bits that will
+// simulate an error on fee query or upload. Defined bits are:
+//
+// 0x01 Simulate application error on fee check reading
+// response body from file "fake_upload_error.xml"
+// 0x02 Same as 0x01 but for actual upload attempt.
+// 0x04 Simulate a transport problem on fee check with a
+// locally-generated 500 status.
+// 0x08 As with 0x04 but for the upload operation.
+//
LLMeshRepository gMeshRepo;
@@ -362,6 +376,14 @@ S32 LLMeshRepoThread::sRequestHighWater = REQUEST_HIGH_WATER_MIN;
// processFailure() methods to customize handling and
// error messages.
//
+// LLCore::HttpHandler
+// LLMeshHandlerBase
+// LLMeshHeaderHandler
+// LLMeshLODHandler
+// LLMeshSkinInfoHandler
+// LLMeshDecompositionHandler
+// LLMeshPhysicsShapeHandler
+
class LLMeshHandlerBase : public LLCore::HttpHandler
{
public:
@@ -534,28 +556,31 @@ public:
};
-void log_upload_error(S32 status, const LLSD& content, std::string stage, std::string model_name)
+void log_upload_error(LLCore::HttpStatus status, const LLSD& content,
+ const char * const stage, const std::string & model_name)
{
// Add notification popup.
LLSD args;
- std::string message = content["error"]["message"];
- std::string identifier = content["error"]["identifier"];
+ std::string message = content["error"]["message"].asString();
+ std::string identifier = content["error"]["identifier"].asString();
args["MESSAGE"] = message;
args["IDENTIFIER"] = identifier;
args["LABEL"] = model_name;
gMeshRepo.uploadError(args);
// Log details.
- llwarns << "stage: " << stage << " http status: " << status << llendl;
+ LL_WARNS(LOG_MESH) << "Error in stage: " << stage
+ << ", Reason: " << status.toString()
+ << " (" << status.toHex() << ")" << LL_ENDL;
if (content.has("error"))
{
const LLSD& err = content["error"];
- llwarns << "err: " << err << llendl;
- llwarns << "mesh upload failed, stage '" << stage
- << "' error '" << err["error"].asString()
- << "', message '" << err["message"].asString()
- << "', id '" << err["identifier"].asString()
- << "'" << llendl;
+ LL_WARNS(LOG_MESH) << "error: " << err << LL_ENDL;
+ LL_WARNS(LOG_MESH) << " mesh upload failed, stage '" << stage
+ << "', error '" << err["error"].asString()
+ << "', message '" << err["message"].asString()
+ << "', id '" << err["identifier"].asString()
+ << "'" << LL_ENDL;
if (err.has("errors"))
{
S32 error_num = 0;
@@ -565,13 +590,13 @@ void log_upload_error(S32 status, const LLSD& content, std::string stage, std::s
++it)
{
const LLSD& err_entry = *it;
- llwarns << "error[" << error_num << "]:" << llendl;
+ LL_WARNS(LOG_MESH) << " error[" << error_num << "]:" << LL_ENDL;
for (LLSD::map_const_iterator map_it = err_entry.beginMap();
map_it != err_entry.endMap();
++map_it)
{
- llwarns << "\t" << map_it->first << ": "
- << map_it->second << llendl;
+ LL_WARNS(LOG_MESH) << " " << map_it->first << ": "
+ << map_it->second << LL_ENDL;
}
error_num++;
}
@@ -579,141 +604,10 @@ void log_upload_error(S32 status, const LLSD& content, std::string stage, std::s
}
else
{
- llwarns << "bad mesh, no error information available" << llendl;
+ LL_WARNS(LOG_MESH) << "Bad response to mesh request, no additional error information available." << LL_ENDL;
}
}
-class LLWholeModelFeeResponder: public LLCurl::Responder
-{
- LLMeshUploadThread* mThread;
- LLSD mModelData;
- LLHandle<LLWholeModelFeeObserver> mObserverHandle;
-public:
- LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelFeeObserver> observer_handle):
- mThread(thread),
- mModelData(model_data),
- mObserverHandle(observer_handle)
- {
- if (mThread)
- {
- mThread->startRequest();
- }
- }
-
- ~LLWholeModelFeeResponder()
- {
- if (mThread)
- {
- mThread->stopRequest();
- }
- }
-
- virtual void completed(U32 status,
- const std::string& reason,
- const LLSD& content)
- {
- LLSD cc = content;
- if (gSavedSettings.getS32("MeshUploadFakeErrors")&1)
- {
- cc = llsd_from_file("fake_upload_error.xml");
- }
-
- dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num));
-
- LLWholeModelFeeObserver* observer = mObserverHandle.get();
-
- if (isGoodStatus(status) &&
- cc["state"].asString() == "upload")
- {
- mThread->mWholeModelUploadURL = cc["uploader"].asString();
-
- if (observer)
- {
- cc["data"]["upload_price"] = cc["upload_price"];
- observer->onModelPhysicsFeeReceived(cc["data"], mThread->mWholeModelUploadURL);
- }
- }
- else
- {
- llwarns << "fee request failed" << llendl;
- log_upload_error(status,cc,"fee",mModelData["name"]);
- mThread->mWholeModelUploadURL = "";
-
- if (observer)
- {
- observer->setModelPhysicsFeeErrorStatus(status, reason);
- }
- }
- }
-
-};
-
-class LLWholeModelUploadResponder: public LLCurl::Responder
-{
- LLMeshUploadThread* mThread;
- LLSD mModelData;
- LLHandle<LLWholeModelUploadObserver> mObserverHandle;
-
-public:
- LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelUploadObserver> observer_handle):
- mThread(thread),
- mModelData(model_data),
- mObserverHandle(observer_handle)
- {
- if (mThread)
- {
- mThread->startRequest();
- }
- }
-
- ~LLWholeModelUploadResponder()
- {
- if (mThread)
- {
- mThread->stopRequest();
- }
- }
-
- virtual void completed(U32 status,
- const std::string& reason,
- const LLSD& content)
- {
- LLSD cc = content;
- if (gSavedSettings.getS32("MeshUploadFakeErrors")&2)
- {
- cc = llsd_from_file("fake_upload_error.xml");
- }
-
- dump_llsd_to_file(cc,make_dump_name("whole_model_upload_response_",dump_num));
-
- LLWholeModelUploadObserver* observer = mObserverHandle.get();
-
- // requested "mesh" asset type isn't actually the type
- // of the resultant object, fix it up here.
- if (isGoodStatus(status) &&
- cc["state"].asString() == "complete")
- {
- mModelData["asset_type"] = "object";
- gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mModelData,cc));
-
- if (observer)
- {
- doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadSuccess, observer));
- }
- }
- else
- {
- llwarns << "upload failed" << llendl;
- std::string model_name = mModelData["name"].asString();
- log_upload_error(status,cc,"upload",model_name);
-
- if (observer)
- {
- doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadFailure, observer));
- }
- }
- }
-};
LLMeshRepoThread::LLMeshRepoThread()
: LLThread("mesh repo"),
@@ -788,7 +682,7 @@ void LLMeshRepoThread::run()
LLCDResult res = LLConvexDecomposition::initThread();
if (res != LLCD_OK)
{
- llwarns << "convex decomposition unable to be loaded" << llendl;
+ LL_WARNS(LOG_MESH) << "Convex decomposition unable to be loaded. Expect severe problems." << LL_ENDL;
}
while (!LLApp::isQuitting())
@@ -923,7 +817,7 @@ void LLMeshRepoThread::run()
res = LLConvexDecomposition::quitThread();
if (res != LLCD_OK)
{
- llwarns << "convex decomposition unable to be quit" << llendl;
+ LL_WARNS(LOG_MESH) << "Convex decomposition unable to be quit." << LL_ENDL;
}
}
@@ -951,7 +845,6 @@ void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32
}
-
void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod)
{ //could be called from any thread
LLMutexLock lock(mMutex);
@@ -1648,7 +1541,7 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
LLMeshSkinInfo info(skin);
info.mMeshID = mesh_id;
- //llinfos<<"info pelvis offset"<<info.mPelvisOffset<<llendl;
+ // LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL;
mSkinInfoQ.push(info);
}
@@ -1739,10 +1632,13 @@ bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32
return true;
}
+
LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
- bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload,
- LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)
-: LLThread("mesh upload"),
+ bool upload_skin, bool upload_joints, const std::string & upload_url, bool do_upload,
+ LLHandle<LLWholeModelFeeObserver> fee_observer,
+ LLHandle<LLWholeModelUploadObserver> upload_observer)
+ : LLThread("mesh upload"),
+ LLCore::HttpHandler(),
mDiscarded(FALSE),
mDoUpload(do_upload),
mWholeModelUploadURL(upload_url),
@@ -1754,7 +1650,6 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mUploadSkin = upload_skin;
mUploadJoints = upload_joints;
mMutex = new LLMutex(NULL);
- mCurlRequest = NULL;
mPendingUploads = 0;
mFinished = false;
mOrigin = gAgent.getPositionAgent();
@@ -1764,12 +1659,31 @@ LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data,
mOrigin += gAgent.getAtAxis() * scale.magVec();
- mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut") ;
+ mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut");
+
+ mHttpRequest = new LLCore::HttpRequest;
+ mHttpOptions = new LLCore::HttpOptions;
+ mHttpOptions->setTransferTimeout(mMeshUploadTimeOut);
+ mHttpHeaders = new LLCore::HttpHeaders;
+ mHttpHeaders->append("Content-Type", "application/llsd+xml");
+ mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicy(LLAppCoreHttp::AP_UPLOADS);
+ mHttpPriority = 0;
}
LLMeshUploadThread::~LLMeshUploadThread()
{
-
+ if (mHttpHeaders)
+ {
+ mHttpHeaders->release();
+ mHttpHeaders = NULL;
+ }
+ if (mHttpOptions)
+ {
+ mHttpOptions->release();
+ mHttpOptions = NULL;
+ }
+ delete mHttpRequest;
+ mHttpRequest = NULL;
}
LLMeshUploadThread::DecompRequest::DecompRequest(LLModel* mdl, LLModel* base_model, LLMeshUploadThread* thread)
@@ -1811,14 +1725,14 @@ void LLMeshUploadThread::preStart()
void LLMeshUploadThread::discard()
{
- LLMutexLock lock(mMutex) ;
- mDiscarded = TRUE ;
+ LLMutexLock lock(mMutex);
+ mDiscarded = TRUE;
}
-BOOL LLMeshUploadThread::isDiscarded()
+BOOL LLMeshUploadThread::isDiscarded() const
{
- LLMutexLock lock(mMutex) ;
- return mDiscarded ;
+ LLMutexLock lock(mMutex);
+ return mDiscarded;
}
void LLMeshUploadThread::run()
@@ -2069,7 +1983,7 @@ void LLMeshUploadThread::generateHulls()
}
}
- if(has_valid_requests)
+ if (has_valid_requests)
{
while (!mPhysicsComplete)
{
@@ -2080,7 +1994,7 @@ void LLMeshUploadThread::generateHulls()
void LLMeshUploadThread::doWholeModelUpload()
{
- mCurlRequest = new LLCurlRequest();
+ LL_DEBUGS(LOG_MESH) << "Starting model upload. Instances: " << mInstance.size() << LL_ENDL;
if (mWholeModelUploadURL.empty())
{
@@ -2090,75 +2004,240 @@ void LLMeshUploadThread::doWholeModelUpload()
else
{
generateHulls();
-
- LLSD full_model_data;
- wholeModelToLLSD(full_model_data, true);
- LLSD body = full_model_data["asset_resources"];
- dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num));
- LLCurlRequest::headers_t headers;
-
+ LL_DEBUGS(LOG_MESH) << "Hull generation completed." << LL_ENDL;
+
+ mModelData = LLSD::emptyMap();
+ wholeModelToLLSD(mModelData, true);
+ LLSD body = mModelData["asset_resources"];
+ dump_llsd_to_file(body, make_dump_name("whole_model_body_", dump_num));
+
+ LLCore::BufferArray * ba = new LLCore::BufferArray;
+ LLCore::BufferArrayStream bas(ba);
+ LLSDSerialize::toXML(body, bas);
+ // LLSDSerialize::toXML(mModelData, bas); // <- This will generate a convenient upload error
+ LLCore::HttpHandle handle = mHttpRequest->requestPost(mHttpPolicyClass,
+ mHttpPriority,
+ mWholeModelUploadURL,
+ ba,
+ mHttpOptions,
+ mHttpHeaders,
+ this);
+ ba->release();
+
+ if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
- LLCurl::ResponderPtr responder = new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle) ;
-
- while(!mCurlRequest->post(mWholeModelUploadURL, headers, body, responder, mMeshUploadTimeOut))
+ mHttpStatus = mHttpRequest->getStatus();
+
+ LL_WARNS(LOG_MESH) << "Couldn't issue request for full model upload. Reason: " << mHttpStatus.toString()
+ << " (" << mHttpStatus.toHex() << ")"
+ << LL_ENDL;
+ }
+ else
+ {
+ U32 sleep_time(10);
+
+ LL_DEBUGS(LOG_MESH) << "POST request issued." << LL_ENDL;
+
+ mHttpRequest->update(0);
+ while (! LLApp::isQuitting() && ! mFinished)
{
- //sleep for 10ms to prevent eating a whole core
- apr_sleep(10000);
+ ms_sleep(sleep_time);
+ sleep_time = llmin(250U, sleep_time + sleep_time);
+ mHttpRequest->update(0);
}
+ LL_DEBUGS(LOG_MESH) << "Mesh upload operation completed." << LL_ENDL;
}
-
- do
- {
- mCurlRequest->process();
- //sleep for 10ms to prevent eating a whole core
- apr_sleep(10000);
- } while (!LLAppViewer::isQuitting() && mPendingUploads > 0);
}
-
- delete mCurlRequest;
- mCurlRequest = NULL;
-
- // Currently a no-op.
- mFinished = true;
}
void LLMeshUploadThread::requestWholeModelFee()
{
dump_num++;
- mCurlRequest = new LLCurlRequest();
-
generateHulls();
- LLSD model_data;
- wholeModelToLLSD(model_data,false);
- dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num));
-
- LLCurlRequest::headers_t headers;
+ mModelData = LLSD::emptyMap();
+ wholeModelToLLSD(mModelData, false);
+ dump_llsd_to_file(mModelData, make_dump_name("whole_model_fee_request_", dump_num));
+ LLCore::BufferArray * ba = new LLCore::BufferArray;
+ LLCore::BufferArrayStream bas(ba);
+ LLSDSerialize::toXML(mModelData, bas);
+
+ LLCore::HttpHandle handle = mHttpRequest->requestPost(mHttpPolicyClass,
+ mHttpPriority,
+ mWholeModelFeeCapability,
+ ba,
+ mHttpOptions,
+ mHttpHeaders,
+ this);
+ ba->release();
+ if (LLCORE_HTTP_HANDLE_INVALID == handle)
{
- LLCurl::ResponderPtr responder = new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle) ;
- while(!mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, responder, mMeshUploadTimeOut))
+ mHttpStatus = mHttpRequest->getStatus();
+
+ LL_WARNS(LOG_MESH) << "Couldn't issue request for model fee. Reason: " << mHttpStatus.toString()
+ << " (" << mHttpStatus.toHex() << ")"
+ << LL_ENDL;
+ }
+ else
+ {
+ U32 sleep_time(10);
+
+ mHttpRequest->update(0);
+ while (! LLApp::isQuitting() && ! mFinished)
{
- //sleep for 10ms to prevent eating a whole core
- apr_sleep(10000);
+ ms_sleep(sleep_time);
+ sleep_time = llmin(250U, sleep_time + sleep_time);
+ mHttpRequest->update(0);
}
}
+}
- do
- {
- mCurlRequest->process();
- //sleep for 10ms to prevent eating a whole core
- apr_sleep(10000);
- } while (!LLApp::isQuitting() && mPendingUploads > 0);
- delete mCurlRequest;
- mCurlRequest = NULL;
+// Does completion duty for both fee queries and actual uploads.
+void LLMeshUploadThread::onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response)
+{
+ // QA/Devel: 0x2 to enable fake error import on upload, 0x1 on fee check
+ const S32 fake_error(gSavedSettings.getS32("MeshUploadFakeErrors") & (mDoUpload ? 0xa : 0x5));
+ LLCore::HttpStatus status(response->getStatus());
+ if (fake_error)
+ {
+ status = (fake_error & 0x0c) ? LLCore::HttpStatus(500) : LLCore::HttpStatus(200);
+ }
+ std::string reason(status.toString());
+ LLSD body;
- // Currently a no-op.
mFinished = true;
+
+ if (mDoUpload)
+ {
+ // model upload case
+ LLWholeModelUploadObserver * observer(mUploadObserverHandle.get());
+
+ if (! status)
+ {
+ LL_WARNS(LOG_MESH) << "Upload failed. Reason: " << reason
+ << " (" << status.toHex() << ")"
+ << LL_ENDL;
+
+ // Build a fake body for the alert generator
+ body["error"] = LLSD::emptyMap();
+ body["error"]["message"] = reason;
+ body["error"]["identifier"] = "NetworkError"; // from asset-upload/upload_util.py
+ log_upload_error(status, body, "upload", mModelData["name"].asString());
+
+ if (observer)
+ {
+ doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadFailure, observer));
+ }
+ }
+ else
+ {
+ if (fake_error & 0x2)
+ {
+ body = llsd_from_file("fake_upload_error.xml");
+ }
+ else
+ {
+ LLCore::BufferArray * ba(response->getBody());
+ if (ba && ba->size())
+ {
+ LLCore::BufferArrayStream bas(ba);
+ LLSDSerialize::fromXML(body, bas);
+ }
+ }
+ dump_llsd_to_file(body, make_dump_name("whole_model_upload_response_", dump_num));
+
+ if (body["state"].asString() == "complete")
+ {
+ // requested "mesh" asset type isn't actually the type
+ // of the resultant object, fix it up here.
+ mModelData["asset_type"] = "object";
+ gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mModelData, body));
+
+ if (observer)
+ {
+ doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadSuccess, observer));
+ }
+ }
+ else
+ {
+ LL_WARNS(LOG_MESH) << "Upload failed. Not in expected 'complete' state." << LL_ENDL;
+ log_upload_error(status, body, "upload", mModelData["name"].asString());
+
+ if (observer)
+ {
+ doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadFailure, observer));
+ }
+ }
+ }
+ }
+ else
+ {
+ // model fee case
+ LLWholeModelFeeObserver* observer(mFeeObserverHandle.get());
+ mWholeModelUploadURL.clear();
+
+ if (! status)
+ {
+ LL_WARNS(LOG_MESH) << "Fee request failed. Reason: " << reason
+ << " (" << status.toHex() << ")"
+ << LL_ENDL;
+
+ // Build a fake body for the alert generator
+ body["error"] = LLSD::emptyMap();
+ body["error"]["message"] = reason;
+ body["error"]["identifier"] = "NetworkError"; // from asset-upload/upload_util.py
+ log_upload_error(status, body, "fee", mModelData["name"].asString());
+
+ if (observer)
+ {
+ observer->setModelPhysicsFeeErrorStatus(status.toULong(), reason);
+ }
+ }
+ else
+ {
+ if (fake_error & 0x1)
+ {
+ body = llsd_from_file("fake_upload_error.xml");
+ }
+ else
+ {
+ LLCore::BufferArray * ba(response->getBody());
+ if (ba && ba->size())
+ {
+ LLCore::BufferArrayStream bas(ba);
+ LLSDSerialize::fromXML(body, bas);
+ }
+ }
+ dump_llsd_to_file(body, make_dump_name("whole_model_fee_response_", dump_num));
+
+ if (body["state"].asString() == "upload")
+ {
+ mWholeModelUploadURL = body["uploader"].asString();
+
+ if (observer)
+ {
+ body["data"]["upload_price"] = body["upload_price"];
+ observer->onModelPhysicsFeeReceived(body["data"], mWholeModelUploadURL);
+ }
+ }
+ else
+ {
+ LL_WARNS(LOG_MESH) << "Fee request failed. Not in expected 'upload' state." << LL_ENDL;
+ log_upload_error(status, body, "fee", mModelData["name"].asString());
+
+ if (observer)
+ {
+ observer->setModelPhysicsFeeErrorStatus(status.toULong(), reason);
+ }
+ }
+ }
+ }
}
+
void LLMeshRepoThread::notifyLoadedMeshes()
{
if (!mMutex)
@@ -2674,13 +2753,13 @@ void LLMeshRepository::init()
void LLMeshRepository::shutdown()
{
- llinfos << "Shutting down mesh repository." << llendl;
+ LL_INFOS(LOG_MESH) << "Shutting down mesh repository." << LL_ENDL;
metrics_teleport_started_signal.disconnect();
for (U32 i = 0; i < mUploads.size(); ++i)
{
- llinfos << "Discard the pending mesh uploads " << llendl;
+ LL_INFOS(LOG_MESH) << "Discard the pending mesh uploads." << LL_ENDL;
mUploads[i]->discard() ; //discard the uploading requests.
}
@@ -2695,7 +2774,7 @@ void LLMeshRepository::shutdown()
for (U32 i = 0; i < mUploads.size(); ++i)
{
- llinfos << "Waiting for pending mesh upload " << i << "/" << mUploads.size() << llendl;
+ LL_INFOS(LOG_MESH) << "Waiting for pending mesh upload " << i << "/" << mUploads.size() << LL_ENDL;
while (!mUploads[i]->isStopped())
{
apr_sleep(10);
@@ -2708,7 +2787,7 @@ void LLMeshRepository::shutdown()
delete mMeshMutex;
mMeshMutex = NULL;
- llinfos << "Shutting down decomposition system." << llendl;
+ LL_INFOS(LOG_MESH) << "Shutting down decomposition system." << LL_ENDL;
if (mDecompThread)
{
@@ -3591,7 +3670,7 @@ void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh, bool vertex_based)
if (ret)
{
- llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl;
+ LL_ERRS(LOG_MESH) << "Convex Decomposition thread valid but could not set mesh data." << LL_ENDL;
}
}
}
@@ -3667,7 +3746,8 @@ void LLPhysicsDecomp::doDecomposition()
if (ret)
{
- llwarns << "Convex Decomposition thread valid but could not execute stage " << stage << llendl;
+ LL_WARNS(LOG_MESH) << "Convex Decomposition thread valid but could not execute stage " << stage << "."
+ << LL_ENDL;
LLMutexLock lock(mMutex);
mCurRequest->mHull.clear();
@@ -3796,9 +3876,9 @@ void LLPhysicsDecomp::doDecompositionSingleHull()
setMeshData(mesh, true);
LLCDResult ret = decomp->buildSingleHull() ;
- if(ret)
+ if (ret)
{
- llwarns << "Could not execute decomposition stage when attempting to create single hull." << llendl;
+ LL_WARNS(LOG_MESH) << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL;
make_box(mCurRequest);
}
else
@@ -4152,7 +4232,7 @@ void LLMeshRepository::metricsUpdate()
metrics["teleports"] = LLSD::Integer(metrics_teleport_start_count);
metrics["user_cpu"] = double(user_cpu) / 1.0e6;
metrics["sys_cpu"] = double(sys_cpu) / 1.0e6;
- llinfos << "EventMarker " << metrics << llendl;
+ LL_INFOS(LOG_MESH) << "EventMarker " << metrics << LL_ENDL;
}
}
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index 96e9feea9d..70079eed23 100755
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -45,8 +45,6 @@
#include "lluploadfloaterobservers.h"
class LLVOVolume;
-class LLMeshResponder;
-class LLCurlRequest;
class LLMutex;
class LLCondition;
class LLVFS;
@@ -396,7 +394,14 @@ private:
U32 mHttpLargeGetCount;
};
-class LLMeshUploadThread : public LLThread
+
+// Class whose instances represent a single upload-type request for
+// meshes: one fee query or one actual upload attempt. Yes, it creates
+// a unique thread for that single request. As it is 1:1, it can also
+// trivially serve as the HttpHandler object for request completion
+// notifications.
+
+class LLMeshUploadThread : public LLThread, public LLCore::HttpHandler
{
private:
S32 mMeshUploadTimeOut ; //maximum time in seconds to execute an uploading request.
@@ -417,44 +422,41 @@ public:
};
LLPointer<DecompRequest> mFinalDecomp;
- bool mPhysicsComplete;
+ volatile bool mPhysicsComplete;
typedef std::map<LLPointer<LLModel>, std::vector<LLVector3> > hull_map;
- hull_map mHullMap;
+ hull_map mHullMap;
typedef std::vector<LLModelInstance> instance_list;
- instance_list mInstanceList;
+ instance_list mInstanceList;
typedef std::map<LLPointer<LLModel>, instance_list> instance_map;
- instance_map mInstance;
+ instance_map mInstance;
- LLMutex* mMutex;
- LLCurlRequest* mCurlRequest;
+ LLMutex* mMutex;
S32 mPendingUploads;
LLVector3 mOrigin;
bool mFinished;
bool mUploadTextures;
bool mUploadSkin;
bool mUploadJoints;
- BOOL mDiscarded ;
+ BOOL mDiscarded;
LLHost mHost;
std::string mWholeModelFeeCapability;
std::string mWholeModelUploadURL;
LLMeshUploadThread(instance_list& data, LLVector3& scale, bool upload_textures,
- bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true,
- LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()), LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
+ bool upload_skin, bool upload_joints, const std::string & upload_url, bool do_upload = true,
+ LLHandle<LLWholeModelFeeObserver> fee_observer = (LLHandle<LLWholeModelFeeObserver>()),
+ LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
~LLMeshUploadThread();
- void startRequest() { ++mPendingUploads; }
- void stopRequest() { --mPendingUploads; }
-
- bool finished() { return mFinished; }
+ bool finished() const { return mFinished; }
virtual void run();
void preStart();
void discard() ;
- BOOL isDiscarded();
+ BOOL isDiscarded() const;
void generateHulls();
@@ -471,11 +473,23 @@ public:
void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; }
void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; }
+ // Inherited from LLCore::HttpHandler
+ virtual void onCompleted(LLCore::HttpHandle handle, LLCore::HttpResponse * response);
+
private:
LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle;
LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle;
bool mDoUpload; // if FALSE only model data will be requested, otherwise the model will be uploaded
+ LLSD mModelData;
+
+ // llcorehttp library interface objects.
+ LLCore::HttpStatus mHttpStatus;
+ LLCore::HttpRequest * mHttpRequest;
+ LLCore::HttpOptions * mHttpOptions;
+ LLCore::HttpHeaders * mHttpHeaders;
+ LLCore::HttpRequest::policy_t mHttpPolicyClass;
+ LLCore::HttpRequest::priority_t mHttpPriority;
};
class LLMeshRepository