diff options
Diffstat (limited to 'indra/newview/llmaterialmgr.cpp')
-rw-r--r-- | indra/newview/llmaterialmgr.cpp | 454 |
1 files changed, 334 insertions, 120 deletions
diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index a1f6a01aa0..f996557c17 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -36,6 +36,9 @@ #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llworld.h" +#include "llhttpsdhandler.h" +#include "httpcommon.h" +#include "llcorehttputil.h" /** * Materials cap parameters @@ -59,56 +62,51 @@ #define MATERIALS_PUT_THROTTLE_SECS 1.f #define MATERIALS_PUT_MAX_ENTRIES 50 -/** - * LLMaterialsResponder helper class - */ -class LLMaterialsResponder : public LLHTTPClient::Responder + +class LLMaterialHttpHandler : public LLHttpSDHandler { -public: - typedef boost::function<void (bool, const LLSD&)> CallbackFunction; +public: + typedef boost::function<void(bool, const LLSD&)> CallbackFunction; + typedef boost::shared_ptr<LLMaterialHttpHandler> ptr_t; - LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback); - virtual ~LLMaterialsResponder(); + LLMaterialHttpHandler(const std::string& method, CallbackFunction cback); - virtual void httpSuccess(); - virtual void httpFailure(); + virtual ~LLMaterialHttpHandler(); + +protected: + virtual void onSuccess(LLCore::HttpResponse * response, const LLSD &content); + virtual void onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status); private: std::string mMethod; - std::string mCapabilityURL; CallbackFunction mCallback; }; -LLMaterialsResponder::LLMaterialsResponder(const std::string& pMethod, const std::string& pCapabilityURL, CallbackFunction pCallback) - : LLHTTPClient::Responder() - , mMethod(pMethod) - , mCapabilityURL(pCapabilityURL) - , mCallback(pCallback) +LLMaterialHttpHandler::LLMaterialHttpHandler(const std::string& method, CallbackFunction cback): + LLHttpSDHandler(), + mMethod(method), + mCallback(cback) { + } -LLMaterialsResponder::~LLMaterialsResponder() +LLMaterialHttpHandler::~LLMaterialHttpHandler() { } -void LLMaterialsResponder::httpSuccess() +void LLMaterialHttpHandler::onSuccess(LLCore::HttpResponse * response, const LLSD &content) { - const LLSD& pContent = getContent(); - LL_DEBUGS("Materials") << LL_ENDL; - mCallback(true, pContent); + mCallback(true, content); } -void LLMaterialsResponder::httpFailure() +void LLMaterialHttpHandler::onFailure(LLCore::HttpResponse * response, LLCore::HttpStatus status) { - U32 pStatus = (U32) getStatus(); - const std::string& pReason = getReason(); - LL_WARNS("Materials") << "\n--------------------------------------------------------------------------\n" - << mMethod << " Error[" << pStatus << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME - << "'\n with url '" << mCapabilityURL << "' because " << pReason + << mMethod << " Error[" << status.toULong() << "] cannot access cap '" << MATERIALS_CAPABILITY_NAME + << "'\n with url '" << response->getRequestURL() << "' because " << status.toString() << "\n--------------------------------------------------------------------------" << LL_ENDL; @@ -116,12 +114,35 @@ void LLMaterialsResponder::httpFailure() mCallback(false, emptyResult); } + + /** * LLMaterialMgr class */ - -LLMaterialMgr::LLMaterialMgr() +LLMaterialMgr::LLMaterialMgr(): + mGetQueue(), + mGetPending(), + mGetCallbacks(), + mGetTECallbacks(), + mGetAllQueue(), + mGetAllRequested(), + mGetAllPending(), + mGetAllCallbacks(), + mPutQueue(), + mMaterials(), + mHttpRequest(), + mHttpHeaders(), + mHttpOptions(), + mHttpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID), + mHttpPriority(0) { + LLAppCoreHttp & app_core_http(LLAppViewer::instance()->getAppCoreHttp()); + + mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest()); + mHttpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders()); + mHttpOptions = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions()); + mHttpPolicy = app_core_http.getPolicy(LLAppCoreHttp::AP_MATERIALS); + mMaterials.insert(std::pair<LLMaterialID, LLMaterialPtr>(LLMaterialID::null, LLMaterialPtr(NULL))); gIdleCallbacks.addFunction(&LLMaterialMgr::onIdle, NULL); LLWorld::instance().setRegionRemovedCallback(boost::bind(&LLMaterialMgr::onRegionRemoved, this, _1)); @@ -554,48 +575,63 @@ void LLMaterialMgr::onIdle(void*) { instancep->processPutQueue(); } + + instancep->mHttpRequest->update(0L); } -void LLMaterialMgr::processGetQueue() +/*static*/ +void LLMaterialMgr::CapsRecvForRegion(const LLUUID& regionId, LLUUID regionTest, std::string pumpname) { - get_queue_t::iterator loopRegionQueue = mGetQueue.begin(); - while (mGetQueue.end() != loopRegionQueue) - { - get_queue_t::iterator itRegionQueue = loopRegionQueue++; - - const LLUUID& region_id = itRegionQueue->first; - if (isGetAllPending(region_id)) - { - continue; - } - - LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id); - if (!regionp) - { - LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL; - mGetQueue.erase(itRegionQueue); - continue; - } - else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled()) - { - continue; - } - else if (mGetAllRequested.end() == mGetAllRequested.find(region_id)) - { - LL_DEBUGS("Materials") << "calling getAll for " << regionp->getName() << LL_ENDL; - getAll(region_id); - continue; - } - - const std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME); - if (capURL.empty()) - { - LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME - << "' is not defined on region '" << regionp->getName() << "'" << LL_ENDL; - mGetQueue.erase(itRegionQueue); - continue; - } + if (regionId == regionTest) + { + LLEventPumps::instance().obtain(pumpname).post(LLSD()); + } +} +void LLMaterialMgr::processGetQueue() +{ + get_queue_t::iterator loopRegionQueue = mGetQueue.begin(); + while (mGetQueue.end() != loopRegionQueue) + { +#if 1 + //* $TODO: This block is screaming to be turned into a coroutine. + // see processGetQueueCoro() below. + // + get_queue_t::iterator itRegionQueue = loopRegionQueue++; + + LLUUID region_id = itRegionQueue->first; + if (isGetAllPending(region_id)) + { + continue; + } + + LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id); + if (!regionp) + { + LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL; + mGetQueue.erase(itRegionQueue); + continue; + } + else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled()) + { + continue; + } + else if (mGetAllRequested.end() == mGetAllRequested.find(region_id)) + { + LL_DEBUGS("Materials") << "calling getAll for " << regionp->getName() << LL_ENDL; + getAll(region_id); + continue; + } + + const std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME); + if (capURL.empty()) + { + LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME + << "' is not defined on region '" << regionp->getName() << "'" << LL_ENDL; + mGetQueue.erase(itRegionQueue); + continue; + } + LLSD materialsData = LLSD::emptyArray(); material_queue_t& materials = itRegionQueue->second; @@ -611,6 +647,7 @@ void LLMaterialMgr::processGetQueue() if (materials.empty()) { mGetQueue.erase(itRegionQueue); + // $TODO*: We may be able to issue a continue here. Research. } std::string materialString = zip_llsd(materialsData); @@ -629,12 +666,123 @@ void LLMaterialMgr::processGetQueue() LLSD postData = LLSD::emptyMap(); postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary; - LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("POST", capURL, boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id)); - LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '"<< capURL << " for " << materialsData.size() << " materials." + LLCore::HttpHandler::ptr_t handler(new LLMaterialHttpHandler("POST", + boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id) + )); + + LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '" << capURL << " for " << materialsData.size() << " materials." << "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL; - LLHTTPClient::post(capURL, postData, materialsResponder); + + LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, + mHttpPolicy, mHttpPriority, capURL, + postData, mHttpOptions, mHttpHeaders, handler); + + if (handle == LLCORE_HTTP_HANDLE_INVALID) + { + LLCore::HttpStatus status = mHttpRequest->getStatus(); + LL_ERRS("Meterials") << "Failed to execute material POST. Status = " << + status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL; + } + regionp->resetMaterialsCapThrottle(); } +#endif +} + +void LLMaterialMgr::processGetQueueCoro() +{ +#if 0 + get_queue_t::iterator itRegionQueue = loopRegionQueue++; + + const LLUUID& region_id = itRegionQueue->first; + if (isGetAllPending(region_id)) + { + continue; + } + + LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id); + if (!regionp) + { + LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL; + mGetQueue.erase(itRegionQueue); + continue; + } + else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled()) + { + continue; + } + else if (mGetAllRequested.end() == mGetAllRequested.find(region_id)) + { + LL_DEBUGS("Materials") << "calling getAll for " << regionp->getName() << LL_ENDL; + getAll(region_id); + continue; + } + + const std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME); + if (capURL.empty()) + { + LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME + << "' is not defined on region '" << regionp->getName() << "'" << LL_ENDL; + mGetQueue.erase(itRegionQueue); + continue; + } + + LLSD materialsData = LLSD::emptyArray(); + + material_queue_t& materials = itRegionQueue->second; + U32 max_entries = regionp->getMaxMaterialsPerTransaction(); + material_queue_t::iterator loopMaterial = materials.begin(); + while ((materials.end() != loopMaterial) && (materialsData.size() < max_entries)) + { + material_queue_t::iterator itMaterial = loopMaterial++; + materialsData.append((*itMaterial).asLLSD()); + materials.erase(itMaterial); + markGetPending(region_id, *itMaterial); + } + if (materials.empty()) + { + mGetQueue.erase(itRegionQueue); + } + + std::string materialString = zip_llsd(materialsData); + + S32 materialSize = materialString.size(); + if (materialSize <= 0) + { + LL_ERRS("Materials") << "cannot zip LLSD binary content" << LL_ENDL; + return; + } + + LLSD::Binary materialBinary; + materialBinary.resize(materialSize); + memcpy(materialBinary.data(), materialString.data(), materialSize); + + LLSD postData = LLSD::emptyMap(); + postData[MATERIALS_CAP_ZIP_FIELD] = materialBinary; + + LLMaterialHttpHandler * handler = + new LLMaterialHttpHandler("POST", + boost::bind(&LLMaterialMgr::onGetResponse, this, _1, _2, region_id) + ); + + LL_DEBUGS("Materials") << "POSTing to region '" << regionp->getName() << "' at '" << capURL << " for " << materialsData.size() << " materials." + << "\ndata: " << ll_pretty_print_sd(materialsData) << LL_ENDL; + + LLCore::HttpHandle handle = LLCoreHttpUtil::requestPostWithLLSD(mHttpRequest, + mHttpPolicy, mHttpPriority, capURL, + postData, mHttpOptions, mHttpHeaders, handler); + + if (handle == LLCORE_HTTP_HANDLE_INVALID) + { + delete handler; + LLCore::HttpStatus status = mHttpRequest->getStatus(); + LL_ERRS("Meterials") << "Failed to execute material POST. Status = " << + status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL; + } + + regionp->resetMaterialsCapThrottle(); +#endif + } void LLMaterialMgr::processGetAllQueue() @@ -645,36 +793,87 @@ void LLMaterialMgr::processGetAllQueue() getall_queue_t::iterator itRegion = loopRegion++; const LLUUID& region_id = *itRegion; - LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(region_id); - if (regionp == NULL) - { - LL_WARNS("Materials") << "Unknown region with id " << region_id.asString() << LL_ENDL; - clearGetQueues(region_id); // Invalidates region_id - continue; - } - else if (!regionp->capabilitiesReceived() || regionp->materialsCapThrottled()) - { - continue; - } - std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME); - if (capURL.empty()) - { - LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME - << "' is not defined on the current region '" << regionp->getName() << "'" << LL_ENDL; - clearGetQueues(region_id); // Invalidates region_id - continue; - } + LLCoros::instance().launch("LLMaterialMgr::processGetAllQueueCoro", boost::bind(&LLMaterialMgr::processGetAllQueueCoro, + this, region_id)); - LL_DEBUGS("Materials") << "GET all for region " << region_id << "url " << capURL << LL_ENDL; - LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("GET", capURL, boost::bind(&LLMaterialMgr::onGetAllResponse, this, _1, _2, *itRegion)); - LLHTTPClient::get(capURL, materialsResponder); - regionp->resetMaterialsCapThrottle(); - mGetAllPending.insert(std::pair<LLUUID, F64>(region_id, LLFrameTimer::getTotalSeconds())); + mGetAllPending.insert(std::pair<LLUUID, F64>(region_id, LLFrameTimer::getTotalSeconds())); mGetAllQueue.erase(itRegion); // Invalidates region_id } } +void LLMaterialMgr::processGetAllQueueCoro(LLUUID regionId) +{ + LLViewerRegion* regionp = LLWorld::instance().getRegionFromID(regionId); + if (regionp == NULL) + { + LL_WARNS("Materials") << "Unknown region with id " << regionId.asString() << LL_ENDL; + clearGetQueues(regionId); // Invalidates region_id + return; + } + else if (!regionp->capabilitiesReceived()) + { + LLEventStream capsRecv("waitForCaps", true); + + regionp->setCapabilitiesReceivedCallback( + boost::bind(&LLMaterialMgr::CapsRecvForRegion, + _1, regionId, capsRecv.getName())); + + llcoro::suspendUntilEventOn(capsRecv); + + // reget the region from the region ID since it may have gone away while waiting. + regionp = LLWorld::instance().getRegionFromID(regionId); + if (!regionp) + { + LL_WARNS("Materials") << "Region with ID " << regionId << " is no longer valid." << LL_ENDL; + return; + } + } + else if (regionp->materialsCapThrottled()) + { + // TODO: + // Figure out how to handle the throttle. + } + + std::string capURL = regionp->getCapability(MATERIALS_CAPABILITY_NAME); + if (capURL.empty()) + { + LL_WARNS("Materials") << "Capability '" << MATERIALS_CAPABILITY_NAME + << "' is not defined on the current region '" << regionp->getName() << "'" << LL_ENDL; + clearGetQueues(regionId); // Invalidates region_id + return; + } + + LL_DEBUGS("Materials") << "GET all for region " << regionId << "url " << capURL << LL_ENDL; + + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter( + new LLCoreHttpUtil::HttpCoroutineAdapter("processGetAllQueue", LLCore::HttpRequest::DEFAULT_POLICY_ID)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); + + LLSD result = httpAdapter->getAndSuspend(httpRequest, capURL); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + if (!status) + { + onGetAllResponse(false, LLSD(), regionId); + } + else + { + onGetAllResponse(true, result, regionId); + } + + // reget the region from the region ID since it may have gone away while waiting. + regionp = LLWorld::instance().getRegionFromID(regionId); + if (!regionp) + { + LL_WARNS("Materials") << "Region with ID " << regionId << " is no longer valid." << LL_ENDL; + return; + } + regionp->resetMaterialsCapThrottle(); +} + void LLMaterialMgr::processPutQueue() { typedef std::map<LLViewerRegion*, LLSD> regionput_request_map; @@ -696,34 +895,34 @@ void LLMaterialMgr::processPutQueue() { LLViewerRegion* regionp = objectp->getRegion(); if ( !regionp ) - { + { LL_WARNS("Materials") << "Object region is NULL" << LL_ENDL; mPutQueue.erase(itQueue); - } + } else if ( regionp->capabilitiesReceived() && !regionp->materialsCapThrottled()) { - LLSD& facesData = requests[regionp]; - - facematerial_map_t& face_map = itQueue->second; - U32 max_entries = regionp->getMaxMaterialsPerTransaction(); - facematerial_map_t::iterator itFace = face_map.begin(); - while ( (face_map.end() != itFace) && (facesData.size() < max_entries) ) - { - LLSD faceData = LLSD::emptyMap(); - faceData[MATERIALS_CAP_FACE_FIELD] = static_cast<LLSD::Integer>(itFace->first); - faceData[MATERIALS_CAP_OBJECT_ID_FIELD] = static_cast<LLSD::Integer>(objectp->getLocalID()); - if (!itFace->second.isNull()) - { - faceData[MATERIALS_CAP_MATERIAL_FIELD] = itFace->second.asLLSD(); - } - facesData.append(faceData); - face_map.erase(itFace++); - } - if (face_map.empty()) - { - mPutQueue.erase(itQueue); - } - } + LLSD& facesData = requests[regionp]; + + facematerial_map_t& face_map = itQueue->second; + U32 max_entries = regionp->getMaxMaterialsPerTransaction(); + facematerial_map_t::iterator itFace = face_map.begin(); + while ( (face_map.end() != itFace) && (facesData.size() < max_entries) ) + { + LLSD faceData = LLSD::emptyMap(); + faceData[MATERIALS_CAP_FACE_FIELD] = static_cast<LLSD::Integer>(itFace->first); + faceData[MATERIALS_CAP_OBJECT_ID_FIELD] = static_cast<LLSD::Integer>(objectp->getLocalID()); + if (!itFace->second.isNull()) + { + faceData[MATERIALS_CAP_MATERIAL_FIELD] = itFace->second.asLLSD(); + } + facesData.append(faceData); + face_map.erase(itFace++); + } + if (face_map.empty()) + { + mPutQueue.erase(itQueue); + } + } } } @@ -755,8 +954,22 @@ void LLMaterialMgr::processPutQueue() putData[MATERIALS_CAP_ZIP_FIELD] = materialBinary; LL_DEBUGS("Materials") << "put for " << itRequest->second.size() << " faces to region " << itRequest->first->getName() << LL_ENDL; - LLHTTPClient::ResponderPtr materialsResponder = new LLMaterialsResponder("PUT", capURL, boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2)); - LLHTTPClient::put(capURL, putData, materialsResponder); + + LLCore::HttpHandler::ptr_t handler (new LLMaterialHttpHandler("PUT", + boost::bind(&LLMaterialMgr::onPutResponse, this, _1, _2) + )); + + LLCore::HttpHandle handle = LLCoreHttpUtil::requestPutWithLLSD( + mHttpRequest, mHttpPolicy, mHttpPriority, capURL, + putData, mHttpOptions, mHttpHeaders, handler); + + if (handle == LLCORE_HTTP_HANDLE_INVALID) + { + LLCore::HttpStatus status = mHttpRequest->getStatus(); + LL_ERRS("Meterials") << "Failed to execute material PUT. Status = " << + status.toULong() << "\"" << status.toString() << "\"" << LL_ENDL; + } + regionp->resetMaterialsCapThrottle(); } else @@ -769,6 +982,7 @@ void LLMaterialMgr::processPutQueue() void LLMaterialMgr::clearGetQueues(const LLUUID& region_id) { mGetQueue.erase(region_id); + for (get_pending_map_t::iterator itPending = mGetPending.begin(); itPending != mGetPending.end();) { if (region_id == itPending->first.first) |