Added a class to automate pumping the HttpRequest on the mainloop.
Converted AccountingCostManager to use the new LLCore::Http library and coroutines.master
parent
fbd58959c2
commit
17641c8427
|
|
@ -29,8 +29,6 @@
|
|||
#define LLAVATARNAMECACHE_H
|
||||
|
||||
#include "llavatarname.h" // for convenience
|
||||
//#include "httpcommon.h"
|
||||
//#include "httpheaders.h"
|
||||
#include <boost/signals2.hpp>
|
||||
|
||||
class LLSD;
|
||||
|
|
|
|||
|
|
@ -279,6 +279,27 @@ void HttpCoroHandler::buildStatusEntry(LLCore::HttpResponse *response, LLCore::H
|
|||
result["http_result"] = httpresults;
|
||||
}
|
||||
|
||||
HttpRequestPumper::HttpRequestPumper(const LLCore::HttpRequest::ptr_t &request):
|
||||
mHttpRequest(request)
|
||||
{
|
||||
mBoundListener = LLEventPumps::instance().obtain("mainloop").
|
||||
listen(LLEventPump::inventName(), boost::bind(&HttpRequestPumper::pollRequest, this, _1));
|
||||
}
|
||||
|
||||
HttpRequestPumper::~HttpRequestPumper()
|
||||
{
|
||||
if (mBoundListener.connected())
|
||||
{
|
||||
mBoundListener.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
bool HttpRequestPumper::pollRequest(const LLSD&)
|
||||
{
|
||||
mHttpRequest->update(0L);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace LLCoreHttpUtil
|
||||
|
||||
|
|
|
|||
|
|
@ -165,8 +165,6 @@ LLCore::HttpHandle requestPutWithLLSD(LLCore::HttpRequest::ptr_t & request,
|
|||
/// +- ["url"] - The URL used to make the call.
|
||||
/// +- ["headers"] - A map of name name value pairs with the HTTP headers.
|
||||
///
|
||||
|
||||
///
|
||||
class HttpCoroHandler : public LLCore::HttpHandler
|
||||
{
|
||||
public:
|
||||
|
|
@ -182,6 +180,22 @@ private:
|
|||
LLEventStream &mReplyPump;
|
||||
};
|
||||
|
||||
/// The HttpRequestPumper is a utility class. When constructed it will poll the
|
||||
/// supplied HttpRequest once per frame until it is destroyed.
|
||||
///
|
||||
class HttpRequestPumper
|
||||
{
|
||||
public:
|
||||
HttpRequestPumper(const LLCore::HttpRequest::ptr_t &request);
|
||||
~HttpRequestPumper();
|
||||
|
||||
private:
|
||||
bool pollRequest(const LLSD&);
|
||||
|
||||
LLTempBoundListener mBoundListener;
|
||||
LLCore::HttpRequest::ptr_t mHttpRequest;
|
||||
};
|
||||
|
||||
} // end namespace LLCoreHttpUtil
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,90 +27,171 @@
|
|||
#include "llviewerprecompiledheaders.h"
|
||||
#include "llaccountingcostmanager.h"
|
||||
#include "llagent.h"
|
||||
#include "llcurl.h"
|
||||
#include "llhttpclient.h"
|
||||
#include "httpcommon.h"
|
||||
#include "llcoros.h"
|
||||
#include "lleventcoro.h"
|
||||
#include "llcorehttputil.h"
|
||||
|
||||
//===============================================================================
|
||||
LLAccountingCostManager::LLAccountingCostManager()
|
||||
LLAccountingCostManager::LLAccountingCostManager():
|
||||
mHttpRequest(),
|
||||
mHttpHeaders(),
|
||||
mHttpOptions(),
|
||||
mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID),
|
||||
mHttpPriority(0)
|
||||
{
|
||||
mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest());
|
||||
mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders(), false);
|
||||
mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions(), false);
|
||||
//mHttpPolicy = LLCore::HttpRequest::DEFAULT_POLICY_ID;
|
||||
|
||||
}
|
||||
//===============================================================================
|
||||
class LLAccountingCostResponder : public LLCurl::Responder
|
||||
|
||||
// Coroutine for sending and processing avatar name cache requests.
|
||||
// Do not call directly. See documentation in lleventcoro.h and llcoro.h for
|
||||
// further explanation.
|
||||
void LLAccountingCostManager::accountingCostCoro(LLCoros::self& self, std::string url,
|
||||
eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle)
|
||||
{
|
||||
LOG_CLASS(LLAccountingCostResponder);
|
||||
public:
|
||||
LLAccountingCostResponder( const LLSD& objectIDs, const LLHandle<LLAccountingCostObserver>& observer_handle )
|
||||
: mObjectIDs( objectIDs ),
|
||||
mObserverHandle( observer_handle )
|
||||
{
|
||||
LLAccountingCostObserver* observer = mObserverHandle.get();
|
||||
if (observer)
|
||||
{
|
||||
mTransactionID = observer->getTransactionID();
|
||||
}
|
||||
}
|
||||
LLEventStream replyPump("AccountingCostReply", true);
|
||||
LLCoreHttpUtil::HttpCoroHandler::ptr_t httpHandler =
|
||||
LLCoreHttpUtil::HttpCoroHandler::ptr_t(new LLCoreHttpUtil::HttpCoroHandler(replyPump));
|
||||
|
||||
void clearPendingRequests ( void )
|
||||
{
|
||||
for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter )
|
||||
{
|
||||
LLAccountingCostManager::getInstance()->removePendingObject( iter->asUUID() );
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void httpFailure()
|
||||
{
|
||||
LL_WARNS() << dumpResponse() << LL_ENDL;
|
||||
clearPendingRequests();
|
||||
LL_DEBUGS("LLAccountingCostManager") << "Entering coroutine " << LLCoros::instance().getName(self)
|
||||
<< " with url '" << url << LL_ENDL;
|
||||
|
||||
LLAccountingCostObserver* observer = mObserverHandle.get();
|
||||
if (observer && observer->getTransactionID() == mTransactionID)
|
||||
{
|
||||
observer->setErrorStatus(getStatus(), getReason());
|
||||
}
|
||||
}
|
||||
|
||||
void httpSuccess()
|
||||
{
|
||||
const LLSD& content = getContent();
|
||||
//Check for error
|
||||
if ( !content.isMap() || content.has("error") )
|
||||
{
|
||||
failureResult(HTTP_INTERNAL_ERROR, "Error on fetched data", content);
|
||||
return;
|
||||
}
|
||||
else if (content.has("selected"))
|
||||
{
|
||||
F32 physicsCost = 0.0f;
|
||||
F32 networkCost = 0.0f;
|
||||
F32 simulationCost = 0.0f;
|
||||
try
|
||||
{
|
||||
LLSD objectList;
|
||||
U32 objectIndex = 0;
|
||||
|
||||
physicsCost = content["selected"]["physics"].asReal();
|
||||
networkCost = content["selected"]["streaming"].asReal();
|
||||
simulationCost = content["selected"]["simulation"].asReal();
|
||||
|
||||
SelectionCost selectionCost( /*transactionID,*/ physicsCost, networkCost, simulationCost );
|
||||
IDIt IDIter = mObjectList.begin();
|
||||
IDIt IDIterEnd = mObjectList.end();
|
||||
|
||||
LLAccountingCostObserver* observer = mObserverHandle.get();
|
||||
if (observer && observer->getTransactionID() == mTransactionID)
|
||||
{
|
||||
observer->onWeightsUpdate(selectionCost);
|
||||
}
|
||||
}
|
||||
for (; IDIter != IDIterEnd; ++IDIter)
|
||||
{
|
||||
// Check to see if a request for this object has already been made.
|
||||
if (mPendingObjectQuota.find(*IDIter) == mPendingObjectQuota.end())
|
||||
{
|
||||
mPendingObjectQuota.insert(*IDIter);
|
||||
objectList[objectIndex++] = *IDIter;
|
||||
}
|
||||
}
|
||||
|
||||
clearPendingRequests();
|
||||
}
|
||||
|
||||
private:
|
||||
//List of posted objects
|
||||
LLSD mObjectIDs;
|
||||
mObjectList.clear();
|
||||
|
||||
// Current request ID
|
||||
LLUUID mTransactionID;
|
||||
//Post results
|
||||
if (objectList.size() == 0)
|
||||
return;
|
||||
|
||||
std::string keystr;
|
||||
if (selectionType == Roots)
|
||||
{
|
||||
keystr = "selected_roots";
|
||||
}
|
||||
else if (selectionType == Prims)
|
||||
{
|
||||
keystr = "selected_prims";
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "Invalid selection type " << LL_ENDL;
|
||||
mObjectList.clear();
|
||||
mPendingObjectQuota.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD dataToPost = LLSD::emptyMap();
|
||||
dataToPost[keystr.c_str()] = objectList;
|
||||
|
||||
LLAccountingCostObserver* observer = observerHandle.get();
|
||||
LLUUID transactionId = observer->getTransactionID();
|
||||
observer = NULL;
|
||||
|
||||
LLSD results;
|
||||
{ // Scoping block for pumper object
|
||||
LL_INFOS() << "Requesting transaction " << transactionId << LL_ENDL;
|
||||
LLCoreHttpUtil::HttpRequestPumper pumper(mHttpRequest);
|
||||
LLCore::HttpHandle hhandle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest,
|
||||
mHttpPolicy, mHttpPriority, url, dataToPost, mHttpOptions, mHttpHeaders,
|
||||
httpHandler.get());
|
||||
|
||||
if (hhandle == LLCORE_HTTP_HANDLE_INVALID)
|
||||
{
|
||||
LLCore::HttpStatus status = mHttpRequest->getStatus();
|
||||
LL_WARNS() << "Error posting to " << url << " Status=" << status.getStatus() <<
|
||||
" message = " << status.getMessage() << LL_ENDL;
|
||||
mPendingObjectQuota.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
results = waitForEventOn(self, replyPump);
|
||||
LL_INFOS() << "Results for transaction " << transactionId << LL_ENDL;
|
||||
}
|
||||
LLSD httpResults;
|
||||
httpResults = results["http_result"];
|
||||
|
||||
do
|
||||
{
|
||||
observer = observerHandle.get();
|
||||
if ((!observer) || (observer->getTransactionID() != transactionId))
|
||||
{
|
||||
if (!observer)
|
||||
break;
|
||||
LL_WARNS() << "Request transaction Id(" << transactionId
|
||||
<< ") does not match observer's transaction Id("
|
||||
<< observer->getTransactionID() << ")." << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!httpResults["success"].asBoolean())
|
||||
{
|
||||
LL_WARNS() << "Error result from LLCoreHttpUtil::HttpCoroHandler. Code "
|
||||
<< httpResults["status"] << ": '" << httpResults["message"] << "'" << LL_ENDL;
|
||||
if (observer)
|
||||
{
|
||||
observer->setErrorStatus(httpResults["status"].asInteger(), httpResults["message"].asStringRef());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!results.isMap() || results.has("error"))
|
||||
{
|
||||
LL_WARNS() << "Error on fetched data" << LL_ENDL;
|
||||
observer->setErrorStatus(499, "Error on fetched data");
|
||||
break;
|
||||
}
|
||||
|
||||
if (results.has("selected"))
|
||||
{
|
||||
F32 physicsCost = 0.0f;
|
||||
F32 networkCost = 0.0f;
|
||||
F32 simulationCost = 0.0f;
|
||||
|
||||
physicsCost = results["selected"]["physics"].asReal();
|
||||
networkCost = results["selected"]["streaming"].asReal();
|
||||
simulationCost = results["selected"]["simulation"].asReal();
|
||||
|
||||
SelectionCost selectionCost( physicsCost, networkCost, simulationCost);
|
||||
|
||||
observer->onWeightsUpdate(selectionCost);
|
||||
}
|
||||
|
||||
} while (false);
|
||||
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
LL_WARNS() << "Caught exception '" << e.what() << "'" << LL_ENDL;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
LL_WARNS() << "Caught unknown exception." << LL_ENDL;
|
||||
}
|
||||
|
||||
mPendingObjectQuota.clear();
|
||||
}
|
||||
|
||||
// Cost update observer handle
|
||||
LLHandle<LLAccountingCostObserver> mObserverHandle;
|
||||
};
|
||||
//===============================================================================
|
||||
void LLAccountingCostManager::fetchCosts( eSelectionType selectionType,
|
||||
const std::string& url,
|
||||
|
|
@ -119,50 +200,11 @@ void LLAccountingCostManager::fetchCosts( eSelectionType selectionType,
|
|||
// Invoking system must have already determined capability availability
|
||||
if ( !url.empty() )
|
||||
{
|
||||
LLSD objectList;
|
||||
U32 objectIndex = 0;
|
||||
|
||||
IDIt IDIter = mObjectList.begin();
|
||||
IDIt IDIterEnd = mObjectList.end();
|
||||
|
||||
for ( ; IDIter != IDIterEnd; ++IDIter )
|
||||
{
|
||||
// Check to see if a request for this object has already been made.
|
||||
if ( mPendingObjectQuota.find( *IDIter ) == mPendingObjectQuota.end() )
|
||||
{
|
||||
mPendingObjectQuota.insert( *IDIter );
|
||||
objectList[objectIndex++] = *IDIter;
|
||||
}
|
||||
}
|
||||
|
||||
mObjectList.clear();
|
||||
|
||||
//Post results
|
||||
if ( objectList.size() > 0 )
|
||||
{
|
||||
std::string keystr;
|
||||
if ( selectionType == Roots )
|
||||
{
|
||||
keystr="selected_roots";
|
||||
}
|
||||
else
|
||||
if ( selectionType == Prims )
|
||||
{
|
||||
keystr="selected_prims";
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS()<<"Invalid selection type "<<LL_ENDL;
|
||||
mObjectList.clear();
|
||||
mPendingObjectQuota.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
LLSD dataToPost = LLSD::emptyMap();
|
||||
dataToPost[keystr.c_str()] = objectList;
|
||||
std::string coroname =
|
||||
LLCoros::instance().launch("LLAccountingCostManager::accountingCostCoro",
|
||||
boost::bind(&LLAccountingCostManager::accountingCostCoro, this, _1, url, selectionType, observer_handle));
|
||||
LL_DEBUGS() << coroname << " with url '" << url << LL_ENDL;
|
||||
|
||||
LLHTTPClient::post( url, dataToPost, new LLAccountingCostResponder( objectList, observer_handle ));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,6 +30,13 @@
|
|||
#include "llhandle.h"
|
||||
|
||||
#include "llaccountingcost.h"
|
||||
#include "httpcommon.h"
|
||||
#include "llcoros.h"
|
||||
#include "lleventcoro.h"
|
||||
#include "httprequest.h"
|
||||
#include "httpheaders.h"
|
||||
#include "httpoptions.h"
|
||||
|
||||
//===============================================================================
|
||||
// An interface class for panels which display the parcel accounting information.
|
||||
class LLAccountingCostObserver
|
||||
|
|
@ -69,6 +76,14 @@ private:
|
|||
//a fetch has been instigated.
|
||||
std::set<LLUUID> mPendingObjectQuota;
|
||||
typedef std::set<LLUUID>::iterator IDIt;
|
||||
|
||||
void accountingCostCoro(LLCoros::self& self, std::string url, eSelectionType selectionType, const LLHandle<LLAccountingCostObserver> observerHandle);
|
||||
|
||||
LLCore::HttpRequest::ptr_t mHttpRequest;
|
||||
LLCore::HttpHeaders::ptr_t mHttpHeaders;
|
||||
LLCore::HttpOptions::ptr_t mHttpOptions;
|
||||
LLCore::HttpRequest::policy_t mHttpPolicy;
|
||||
LLCore::HttpRequest::priority_t mHttpPriority;
|
||||
};
|
||||
//===============================================================================
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue