Add AIMeshUpload and fix LLMeshUploadThread

* Removes polling stuff (call to gMeshRepo.update()) which did
  nothing but check if uploads already finished.
* Just creates and runs the state machine (AIMeshUpload) instead
  of creating an LLThread derived class (LLMeshUploadThread) and
  adding that to a queue, then have the main thread start it
  after adding it to another queue in order to keep track of
  the instances (both queues are gone).
* mWholeModelUploadURL was moved to the state machine, because
  it needs a life time till the responders finishes (can't be
  part of the thread object).
* LLMeshUploadThread is now derived from AIThreadImpl instead
  of LLThread, so it can be run in a state machine thread.
* The call to LLHTTPClient::post is now done from the main
  thread instead of from the thread, but I don't think that is
  a problem.
This commit is contained in:
Aleric Inglewood
2013-01-29 23:21:37 +01:00
parent b3adf71ed7
commit 1d673df1bd
3 changed files with 136 additions and 164 deletions

View File

@@ -1310,7 +1310,6 @@ bool LLAppViewer::mainLoop()
break;
}
}
gMeshRepo.update() ;
if ((LLStartUp::getStartupState() >= STATE_CLEANUP) &&
(frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD))
{

View File

@@ -371,27 +371,19 @@ void log_upload_error(S32 status, const LLSD& content, std::string stage, std::s
class LLWholeModelFeeResponder : public LLHTTPClient::ResponderWithCompleted
{
LLMeshUploadThread* mThread;
std::string& mWholeModelUploadURL;
LLSD mModelData;
LLHandle<LLWholeModelFeeObserver> mObserverHandle;
public:
LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelFeeObserver> observer_handle):
mThread(thread),
LLWholeModelFeeResponder(LLSD& model_data, LLHandle<LLWholeModelFeeObserver> observer_handle, std::string& url_out):
mWholeModelUploadURL(url_out),
mModelData(model_data),
mObserverHandle(observer_handle)
{
if (mThread)
{
mThread->startRequest();
}
}
~LLWholeModelFeeResponder()
{
if (mThread)
{
mThread->stopRequest();
}
}
/*virtual*/ void completed(U32 status,
@@ -411,19 +403,19 @@ public:
if (((200 <= status) && (status < 300)) &&
cc["state"].asString() == "upload")
{
mThread->mWholeModelUploadURL = cc["uploader"].asString();
mWholeModelUploadURL = cc["uploader"].asString();
if (observer)
{
cc["data"]["upload_price"] = cc["upload_price"];
observer->onModelPhysicsFeeReceived(cc["data"], mThread->mWholeModelUploadURL);
observer->onModelPhysicsFeeReceived(cc["data"], mWholeModelUploadURL);
}
}
else
{
llwarns << "fee request failed" << llendl;
log_upload_error(status,cc,"fee",mModelData["name"]);
mThread->mWholeModelUploadURL = "";
mWholeModelUploadURL = "";
if (observer)
{
@@ -438,28 +430,18 @@ public:
class LLWholeModelUploadResponder : public LLHTTPClient::ResponderWithCompleted
{
LLMeshUploadThread* mThread;
LLSD mModelData;
LLHandle<LLWholeModelUploadObserver> mObserverHandle;
public:
LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelUploadObserver> observer_handle):
mThread(thread),
LLWholeModelUploadResponder(LLSD& model_data, LLHandle<LLWholeModelUploadObserver> observer_handle):
mModelData(model_data),
mObserverHandle(observer_handle)
{
if (mThread)
{
mThread->startRequest();
}
}
~LLWholeModelUploadResponder()
{
if (mThread)
{
mThread->stopRequest();
}
}
/*virtual*/ void completed(U32 status,
@@ -1288,22 +1270,21 @@ 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"),
mDiscarded(FALSE),
mDoUpload(do_upload),
mWholeModelUploadURL(upload_url),
mFeeObserverHandle(fee_observer),
mUploadObserverHandle(upload_observer)
LLMeshUploadThread::LLMeshUploadThread(AIStateMachineThreadBase* state_machine_thread) : AIThreadImpl(state_machine_thread, "mesh upload")
{
}
void LLMeshUploadThread::init(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures,
bool upload_skin, bool upload_joints, bool do_upload,
LLHandle<LLWholeModelFeeObserver> const& fee_observer, LLHandle<LLWholeModelUploadObserver> const& upload_observer)
{
mDoUpload = do_upload;
mFeeObserverHandle = fee_observer;
mUploadObserverHandle = upload_observer;
mInstanceList = data;
mUploadTextures = upload_textures;
mUploadSkin = upload_skin;
mUploadJoints = upload_joints;
mMutex = new LLMutex();
mPendingUploads = 0;
mOrigin = gAgent.getPositionAgent();
mHost = gAgent.getRegionHost();
@@ -1356,28 +1337,86 @@ void LLMeshUploadThread::preStart()
}
}
void LLMeshUploadThread::discard()
AIMeshUpload::AIMeshUpload(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures, bool upload_skin, bool upload_joints, std::string const& upload_url, bool do_upload,
LLHandle<LLWholeModelFeeObserver> const& fee_observer, LLHandle<LLWholeModelUploadObserver> const& upload_observer) : mWholeModelUploadURL(upload_url)
{
LLMutexLock lock(mMutex) ;
mDiscarded = TRUE ;
mMeshUpload->init(data, scale, upload_textures, upload_skin, upload_joints, do_upload, fee_observer, upload_observer);
}
BOOL LLMeshUploadThread::isDiscarded()
char const* AIMeshUpload::state_str_impl(state_type run_state) const
{
LLMutexLock lock(mMutex) ;
return mDiscarded ;
}
void LLMeshUploadThread::run()
{
if (mDoUpload)
switch (run_state)
{
doWholeModelUpload();
AI_CASE_RETURN(AIMeshUpload_start);
AI_CASE_RETURN(AIMeshUpload_threadFinished);
AI_CASE_RETURN(AIMeshUpload_responderFinished);
}
return "UNKNOWN STATE";
}
void AIMeshUpload::initialize_impl()
{
mMeshUpload->preStart();
set_state(AIMeshUpload_start);
}
void AIMeshUpload::multiplex_impl()
{
switch (mRunState)
{
case AIMeshUpload_start:
mMeshUpload.run(this, AIMeshUpload_threadFinished);
idle(AIMeshUpload_start); // Wait till the thread finished.
break;
case AIMeshUpload_threadFinished:
mMeshUpload->postRequest(mWholeModelUploadURL, this);
idle(AIMeshUpload_threadFinished); // Wait till the responder finished.
break;
case AIMeshUpload_responderFinished:
finish();
break;
}
}
bool LLMeshUploadThread::run()
{
generateHulls();
wholeModelToLLSD(mModelData, mDoUpload);
if (!mDoUpload)
{
++dump_num;
dump_llsd_to_file(mModelData, make_dump_name("whole_model_fee_request_", dump_num));
}
else
{
requestWholeModelFee();
mBody = mModelData["asset_resources"];
dump_llsd_to_file(mBody, make_dump_name("whole_model_body_", dump_num));
}
return true; // true = finish, false = abort.
}
void LLMeshUploadThread::postRequest(std::string& whole_model_upload_url, AIMeshUpload* state_machine)
{
if (!mDoUpload)
{
LLHTTPClient::post(mWholeModelFeeCapability, mModelData,
new LLWholeModelFeeResponder(mModelData, mFeeObserverHandle, whole_model_upload_url)/*,*/
DEBUG_CURLIO_PARAM(debug_on), keep_alive, state_machine, AIMeshUpload_responderFinished);
}
else
{
LLHTTPClient::post(whole_model_upload_url, mBody,
new LLWholeModelUploadResponder(mModelData, mUploadObserverHandle)/*,*/
DEBUG_CURLIO_PARAM(debug_off), keep_alive, state_machine, AIMeshUpload_responderFinished);
}
}
void AIMeshUpload::abort_impl()
{
}
void AIMeshUpload::finish_impl()
{
}
void dump_llsd_to_file(const LLSD& content, std::string filename)
@@ -1625,40 +1664,6 @@ void LLMeshUploadThread::generateHulls()
}
}
void LLMeshUploadThread::doWholeModelUpload()
{
if (mWholeModelUploadURL.empty())
{
llinfos << "unable to upload, fee request failed" << llendl;
}
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));
LLHTTPClient::post(mWholeModelUploadURL, body,
new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle));
}
}
void LLMeshUploadThread::requestWholeModelFee()
{
dump_num++;
generateHulls();
LLSD model_data;
wholeModelToLLSD(model_data,false);
dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num));
// This might throw AICurlNoEasyHandle.
LLHTTPClient::post(mWholeModelFeeCapability, model_data,
new LLWholeModelFeeResponder(this, model_data, mFeeObserverHandle));
}
void LLMeshRepoThread::notifyLoadedMeshes()
{//called via gMeshRepo.notifyLoadedMeshes(). mMutex already locked
while (!mLoadedQ.empty())
@@ -2134,12 +2139,6 @@ void LLMeshRepository::shutdown()
{
llinfos << "Shutting down mesh repository." << llendl;
for (U32 i = 0; i < mUploads.size(); ++i)
{
llinfos << "Discard the pending mesh uploads " << llendl;
mUploads[i]->discard() ; //discard the uploading requests.
}
mThread->mSignal->signal();
while (!mThread->isStopped())
@@ -2149,18 +2148,6 @@ void LLMeshRepository::shutdown()
delete mThread;
mThread = NULL;
for (U32 i = 0; i < mUploads.size(); ++i)
{
llinfos << "Waiting for pending mesh upload " << i << "/" << mUploads.size() << llendl;
while (!mUploads[i]->isStopped())
{
apr_sleep(10);
}
delete mUploads[i];
}
mUploads.clear();
delete mMeshMutex;
mMeshMutex = NULL;
@@ -2176,27 +2163,6 @@ void LLMeshRepository::shutdown()
LLConvexDecomposition::quitSystem();
}
//called in the main thread.
S32 LLMeshRepository::update()
{
S32 size = 0;
if(mUploadWaitList.empty())
{
return 0 ;
}
size = mUploadWaitList.size() ;
for (S32 i = 0; i < size; ++i)
{
mUploads.push_back(mUploadWaitList[i]);
mUploadWaitList[i]->preStart() ;
mUploadWaitList[i]->start() ;
}
mUploadWaitList.clear() ;
return size ;
}
S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail, S32 last_lod)
{
if (detail < 0 || detail > 4)
@@ -2280,22 +2246,6 @@ void LLMeshRepository::notifyLoadedMeshes()
static const LLCachedControl<U32> max_concurrent_requests("MeshMaxConcurrentRequests");
LLMeshRepoThread::sMaxConcurrentRequests = max_concurrent_requests;
//clean up completed upload threads
for (std::vector<LLMeshUploadThread*>::iterator iter = mUploads.begin(); iter != mUploads.end(); )
{
LLMeshUploadThread* thread = *iter;
if (thread->isStopped())
{
iter = mUploads.erase(iter);
delete thread;
}
else
{
++iter;
}
}
//update inventory
if (!mInventoryQ.empty())
{
@@ -2720,9 +2670,13 @@ void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3
bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload,
LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer)
{
LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures, upload_skin, upload_joints, upload_url,
do_upload, fee_observer, upload_observer);
mUploadWaitList.push_back(thread);
if (do_upload && upload_url.empty())
{
llinfos << "unable to upload, fee request failed" << llendl;
return;
}
AIMeshUpload* uploader = new AIMeshUpload(data, scale, upload_textures, upload_skin, upload_joints, upload_url, do_upload, fee_observer, upload_observer);
uploader->run();
}
S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod)

View File

@@ -37,6 +37,7 @@
#include "LLConvexDecomposition.h"
#include "lluploadfloaterobservers.h"
#include "aistatemachinethread.h"
class LLVOVolume;
class LLMeshResponder;
@@ -44,6 +45,7 @@ class LLMutex;
class LLCondition;
class LLVFS;
class LLMeshRepository;
class AIMeshUpload;
class LLMeshUploadData
{
@@ -350,7 +352,7 @@ public:
};
class LLMeshUploadThread : public LLThread
class LLMeshUploadThread : public AIThreadImpl
{
private:
S32 mMeshUploadTimeOut ; //maximum time in seconds to execute an uploading request.
@@ -372,6 +374,8 @@ public:
LLPointer<DecompRequest> mFinalDecomp;
bool mPhysicsComplete;
LLSD mModelData;
LLSD mBody;
typedef std::map<LLPointer<LLModel>, std::vector<LLVector3> > hull_map;
hull_map mHullMap;
@@ -382,36 +386,25 @@ public:
typedef std::map<LLPointer<LLModel>, instance_list> instance_map;
instance_map mInstance;
LLMutex* mMutex;
S32 mPendingUploads;
LLVector3 mOrigin;
bool mUploadTextures;
bool mUploadSkin;
bool mUploadJoints;
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>()));
LLMeshUploadThread(AIStateMachineThreadBase* state_machine_thread);
~LLMeshUploadThread();
void init(instance_list& data, LLVector3& scale, bool upload_textures, bool upload_skin, bool upload_joints, bool do_upload,
LLHandle<LLWholeModelFeeObserver> const& fee_observer, LLHandle<LLWholeModelUploadObserver> const& upload_observer);
void postRequest(std::string& url, AIMeshUpload* state_machine);
void startRequest() { ++mPendingUploads; }
void stopRequest() { --mPendingUploads; }
virtual void run();
/*virtual*/ bool run();
void preStart();
void discard() ;
BOOL isDiscarded();
void generateHulls();
void doWholeModelUpload();
void requestWholeModelFee();
void wholeModelToLLSD(LLSD& dest, bool include_textures);
void decomposeMeshMatrix(LLMatrix4& transformation,
@@ -429,6 +422,34 @@ private:
bool mDoUpload; // if FALSE only model data will be requested, otherwise the model will be uploaded
};
enum AIMeshUpload_state_type {
AIMeshUpload_start = AIStateMachine::max_state,
AIMeshUpload_threadFinished,
AIMeshUpload_responderFinished
};
class AIMeshUpload : public AIStateMachine
{
private:
AIStateMachineThread<LLMeshUploadThread> mMeshUpload;
std::string mWholeModelUploadURL;
public:
AIMeshUpload(LLMeshUploadThread::instance_list& data, LLVector3& scale,
bool upload_textures, bool upload_skin, bool upload_joints, std::string const& upload_url, bool do_upload,
LLHandle<LLWholeModelFeeObserver> const& fee_observer, LLHandle<LLWholeModelUploadObserver> const& upload_observer);
void setWholeModelUploadURL(std::string const& whole_model_upload_url) { mWholeModelUploadURL = whole_model_upload_url; }
protected:
// Implement AIStateMachine.
/*virtual*/ const char* state_str_impl(state_type) const;
/*virtual*/ void initialize_impl();
/*virtual*/ void multiplex_impl();
/*virtual*/ void abort_impl();
/*virtual*/ void finish_impl();
};
class LLMeshRepository
{
public:
@@ -449,7 +470,6 @@ public:
void init();
void shutdown();
S32 update() ;
//mesh management functions
S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1);
@@ -477,8 +497,9 @@ public:
LLSD& getMeshHeader(const LLUUID& mesh_id);
void uploadModel(std::vector<LLModelInstance>& 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, std::string upload_url, bool do_upload = true,
LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()),
LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>()));
S32 getMeshSize(const LLUUID& mesh_id, S32 lod);
@@ -519,8 +540,6 @@ public:
void cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header);
LLMeshRepoThread* mThread;
std::vector<LLMeshUploadThread*> mUploads;
std::vector<LLMeshUploadThread*> mUploadWaitList;
LLPhysicsDecomp* mDecompThread;