From a035d78e25551a77a7a1513c3cee8b9dca117540 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 23 Jul 2015 11:28:21 -0700 Subject: AR Reports now use coroutines. --- indra/newview/llfloaterreporter.cpp | 107 +++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 43 deletions(-) (limited to 'indra/newview/llfloaterreporter.cpp') diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 5e028e6d43..b38362e180 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -83,6 +83,61 @@ #include "lltrans.h" #include "llexperiencecache.h" +#include "llcorehttputil.h" +#include "llviewerassetupload.h" + + +//========================================================================= +//----------------------------------------------------------------------------- +// Support classes +//----------------------------------------------------------------------------- +class LLARScreenShotUploader : public LLResourceUploadInfo +{ +public: + LLARScreenShotUploader(LLSD report, LLUUID assetId, LLAssetType::EType assetType); + + virtual LLSD prepareUpload(); + virtual LLSD generatePostBody(); + virtual S32 getEconomyUploadCost(); + virtual LLUUID finishUpload(LLSD &result); + + virtual bool showInventoryPanel() const { return false; } + virtual std::string getDisplayName() const { return "Abuse Report"; } + +private: + + LLSD mReport; +}; + +LLARScreenShotUploader::LLARScreenShotUploader(LLSD report, LLUUID assetId, LLAssetType::EType assetType) : + LLResourceUploadInfo(assetId, assetType, "Abuse Report"), + mReport(report) +{ +} + +LLSD LLARScreenShotUploader::prepareUpload() +{ + return LLSD().with("success", LLSD::Boolean(true)); +} + +LLSD LLARScreenShotUploader::generatePostBody() +{ // The report was pregenerated and passed in the constructor. + return mReport; +} + +S32 LLARScreenShotUploader::getEconomyUploadCost() +{ // Abuse report screen shots do not cost anything to upload. + return 0; +} + +LLUUID LLARScreenShotUploader::finishUpload(LLSD &result) +{ + /* *TODO$: Report success or failure. Carried over from previous todo on responder*/ + return LLUUID::null; +} + + +//========================================================================= //----------------------------------------------------------------------------- // Globals //----------------------------------------------------------------------------- @@ -724,59 +779,25 @@ void LLFloaterReporter::sendReportViaLegacy(const LLSD & report) msg->sendReliable(regionp->getHost()); } -class LLUserReportScreenshotResponder : public LLAssetUploadResponder +void LLFloaterReporter::finishedARPost(const LLSD &) { -public: - LLUserReportScreenshotResponder(const LLSD & post_data, - const LLUUID & vfile_id, - LLAssetType::EType asset_type): - LLAssetUploadResponder(post_data, vfile_id, asset_type) - { - } - void uploadFailed(const LLSD& content) - { - // *TODO pop up a dialog so the user knows their report screenshot didn't make it - LLUploadDialog::modalUploadFinished(); - } - void uploadComplete(const LLSD& content) - { - // we don't care about what the server returns from this post, just clean up the UI - LLUploadDialog::modalUploadFinished(); - } -}; + LLUploadDialog::modalUploadFinished(); -class LLUserReportResponder : public LLHTTPClient::Responder -{ - LOG_CLASS(LLUserReportResponder); -public: - LLUserReportResponder(): LLHTTPClient::Responder() {} - -private: - void httpCompleted() - { - if (!isGoodStatus()) - { - // *TODO do some user messaging here - LL_WARNS("UserReport") << dumpResponse() << LL_ENDL; - } - // we don't care about what the server returns - LLUploadDialog::modalUploadFinished(); - } -}; +} void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report) { if(getChild("screen_check")->getValue().asBoolean() && !sshot_url.empty()) - { + { // try to upload screenshot - LLHTTPClient::post(sshot_url, report, new LLUserReportScreenshotResponder(report, - mResourceDatap->mAssetInfo.mUuid, - mResourceDatap->mAssetInfo.mType)); + LLResourceUploadInfo::ptr_t uploadInfo(new LLARScreenShotUploader(report, mResourceDatap->mAssetInfo.mUuid, mResourceDatap->mAssetInfo.mType)); + LLViewerAssetUpload::EnqueueInventoryUpload(sshot_url, uploadInfo); } else { - // screenshot not wanted or we don't have screenshot cap - LLHTTPClient::post(url, report, new LLUserReportResponder()); + LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t proc = boost::bind(&LLFloaterReporter::finishedARPost, _1); + LLUploadDialog::modalUploadDialog("Abuse Report"); + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpPost(url, report, proc, proc); } } -- cgit v1.3 From 7882396811fdf8b297f6d0c92d8e1e37859fde9d Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 23 Jul 2015 13:06:24 -0700 Subject: Remove unused code and llassetuploadresponders files. --- indra/newview/CMakeLists.txt | 2 - indra/newview/llassetuploadresponders.cpp | 1153 ----------------------------- indra/newview/llassetuploadresponders.h | 158 ---- indra/newview/llcompilequeue.cpp | 1 - indra/newview/llfloaterreporter.cpp | 1 - indra/newview/llmeshrepository.cpp | 134 ++++ indra/newview/llpostcard.cpp | 1 - indra/newview/llpreviewgesture.cpp | 1 - indra/newview/llpreviewnotecard.cpp | 1 - indra/newview/llpreviewscript.cpp | 1 - indra/newview/llviewermenufile.cpp | 1 - indra/newview/llviewermenufile.h | 10 - 12 files changed, 134 insertions(+), 1330 deletions(-) delete mode 100755 indra/newview/llassetuploadresponders.cpp delete mode 100755 indra/newview/llassetuploadresponders.h (limited to 'indra/newview/llfloaterreporter.cpp') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e79fa8b084..fd4f9f7f45 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -123,7 +123,6 @@ set(viewer_SOURCE_FILES llappearancemgr.cpp llappviewer.cpp llappviewerlistener.cpp - llassetuploadresponders.cpp llattachmentsmgr.cpp llaudiosourcevo.cpp llautoreplace.cpp @@ -734,7 +733,6 @@ set(viewer_HEADER_FILES llappearancemgr.h llappviewer.h llappviewerlistener.h - llassetuploadresponders.h llattachmentsmgr.h llaudiosourcevo.h llautoreplace.h diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp deleted file mode 100755 index f62c57b2b3..0000000000 --- a/indra/newview/llassetuploadresponders.cpp +++ /dev/null @@ -1,1153 +0,0 @@ -/** - * @file llassetuploadresponders.cpp - * @brief Processes responses received for asset upload requests. - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llassetuploadresponders.h" - -// viewer includes -#include "llagent.h" -#include "llcompilequeue.h" -#include "llbuycurrencyhtml.h" -#include "llfilepicker.h" -#include "llinventorydefines.h" -#include "llinventoryobserver.h" -#include "llinventorypanel.h" -#include "llpermissionsflags.h" -#include "llpreviewnotecard.h" -#include "llpreviewscript.h" -#include "llpreviewgesture.h" -#include "llgesturemgr.h" -#include "llstatusbar.h" // sendMoneyBalanceRequest() -#include "llsdserialize.h" -#include "lluploaddialog.h" -#include "llviewerobject.h" -#include "llviewercontrol.h" -#include "llviewerobjectlist.h" -#include "llviewermenufile.h" -#include "llviewertexlayer.h" -#include "llviewerwindow.h" -#include "lltrans.h" - -// library includes -#include "lldir.h" -#include "lleconomy.h" -#include "llfloaterreg.h" -#include "llfocusmgr.h" -#include "llnotificationsutil.h" -#include "llscrolllistctrl.h" -#include "llsdserialize.h" -#include "llsdutil.h" -#include "llvfs.h" - -void dialog_refresh_all(); - -void on_new_single_inventory_upload_complete( - LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - const std::string inventory_type_string, - const LLUUID& item_folder_id, - const std::string& item_name, - const std::string& item_description, - const LLSD& server_response, - S32 upload_price) -{ - bool success = false; - - if ( upload_price > 0 ) - { - // this upload costed us L$, update our balance - // and display something saying that it cost L$ - LLStatusBar::sendMoneyBalanceRequest(); - - LLSD args; - args["AMOUNT"] = llformat("%d", upload_price); - LLNotificationsUtil::add("UploadPayment", args); - } - - if( item_folder_id.notNull() ) - { - U32 everyone_perms = PERM_NONE; - U32 group_perms = PERM_NONE; - U32 next_owner_perms = PERM_ALL; - if( server_response.has("new_next_owner_mask") ) - { - // The server provided creation perms so use them. - // Do not assume we got the perms we asked for in - // since the server may not have granted them all. - everyone_perms = server_response["new_everyone_mask"].asInteger(); - group_perms = server_response["new_group_mask"].asInteger(); - next_owner_perms = server_response["new_next_owner_mask"].asInteger(); - } - else - { - // The server doesn't provide creation perms - // so use old assumption-based perms. - if( inventory_type_string != "snapshot") - { - next_owner_perms = PERM_MOVE | PERM_TRANSFER; - } - } - - LLPermissions new_perms; - new_perms.init( - gAgent.getID(), - gAgent.getID(), - LLUUID::null, - LLUUID::null); - - new_perms.initMasks( - PERM_ALL, - PERM_ALL, - everyone_perms, - group_perms, - next_owner_perms); - - U32 inventory_item_flags = 0; - if (server_response.has("inventory_flags")) - { - inventory_item_flags = (U32) server_response["inventory_flags"].asInteger(); - if (inventory_item_flags != 0) - { - LL_INFOS() << "inventory_item_flags " << inventory_item_flags << LL_ENDL; - } - } - S32 creation_date_now = time_corrected(); - LLPointer item = new LLViewerInventoryItem( - server_response["new_inventory_item"].asUUID(), - item_folder_id, - new_perms, - server_response["new_asset"].asUUID(), - asset_type, - inventory_type, - item_name, - item_description, - LLSaleInfo::DEFAULT, - inventory_item_flags, - creation_date_now); - - gInventory.updateItem(item); - gInventory.notifyObservers(); - success = true; - - // Show the preview panel for textures and sounds to let - // user know that the image (or snapshot) arrived intact. - LLInventoryPanel* panel = LLInventoryPanel::getActiveInventoryPanel(); - if ( panel ) - { - LLFocusableElement* focus = gFocusMgr.getKeyboardFocus(); - - panel->setSelection( - server_response["new_inventory_item"].asUUID(), - TAKE_FOCUS_NO); - - // restore keyboard focus - gFocusMgr.setKeyboardFocus(focus); - } - } - else - { - LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL; - } - - // remove the "Uploading..." message - LLUploadDialog::modalUploadFinished(); - - // Let the Snapshot floater know we have finished uploading a snapshot to inventory. - LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); - if (asset_type == LLAssetType::AT_TEXTURE && floater_snapshot) - { - floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory"))); - } -} - -LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type) - : LLHTTPClient::Responder(), - mPostData(post_data), - mVFileID(vfile_id), - mAssetType(asset_type) -{ - if (!gVFS->getExists(vfile_id, asset_type)) - { - LL_WARNS() << "LLAssetUploadResponder called with nonexistant vfile_id" << LL_ENDL; - mVFileID.setNull(); - mAssetType = LLAssetType::AT_NONE; - return; - } -} - -LLAssetUploadResponder::LLAssetUploadResponder( - const LLSD &post_data, - const std::string& file_name, - LLAssetType::EType asset_type) - : LLHTTPClient::Responder(), - mPostData(post_data), - mFileName(file_name), - mAssetType(asset_type) -{ -} - -LLAssetUploadResponder::~LLAssetUploadResponder() -{ - if (!mFileName.empty()) - { - // Delete temp file - LLFile::remove(mFileName); - } -} - -// virtual -void LLAssetUploadResponder::httpFailure() -{ - // *TODO: Add adaptive retry policy? - LL_WARNS() << dumpResponse() << LL_ENDL; - std::string reason; - if (isHttpClientErrorStatus(getStatus())) - { - reason = "Error in upload request. Please visit " - "http://secondlife.com/support for help fixing this problem."; - } - else - { - reason = "The server is experiencing unexpected " - "difficulties."; - } - LLSD args; - args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); - args["REASON"] = reason; - LLNotificationsUtil::add("CannotUploadReason", args); - - // unfreeze script preview - if(mAssetType == LLAssetType::AT_LSL_TEXT) - { - LLPreviewLSL* preview = LLFloaterReg::findTypedInstance("preview_script", mPostData["item_id"]); - if (preview) - { - LLSD errors; - errors.append(LLTrans::getString("UploadFailed") + reason); - preview->callbackLSLCompileFailed(errors); - } - } - - LLUploadDialog::modalUploadFinished(); - LLFilePicker::instance().reset(); // unlock file picker when bulk upload fails -} - -//virtual -void LLAssetUploadResponder::httpSuccess() -{ - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); - return; - } - LL_DEBUGS() << "LLAssetUploadResponder::result from capabilities" << LL_ENDL; - - const std::string& state = content["state"].asStringRef(); - - if (state == "upload") - { - uploadUpload(content); - } - else if (state == "complete") - { - // rename file in VFS with new asset id - if (mFileName.empty()) - { - // rename the file in the VFS to the actual asset id - // LL_INFOS() << "Changing uploaded asset UUID to " << content["new_asset"].asUUID() << LL_ENDL; - gVFS->renameFile(mVFileID, mAssetType, content["new_asset"].asUUID(), mAssetType); - } - uploadComplete(content); - } - else - { - uploadFailure(content); - } -} - -void LLAssetUploadResponder::uploadUpload(const LLSD& content) -{ - const std::string& uploader = content["uploader"].asStringRef(); - if (mFileName.empty()) - { - LLHTTPClient::postFile(uploader, mVFileID, mAssetType, this); - } - else - { - LLHTTPClient::postFile(uploader, mFileName, this); - } -} - -void LLAssetUploadResponder::uploadFailure(const LLSD& content) -{ - LL_WARNS() << dumpResponse() << LL_ENDL; - - // unfreeze script preview - if(mAssetType == LLAssetType::AT_LSL_TEXT) - { - LLPreviewLSL* preview = LLFloaterReg::findTypedInstance("preview_script", mPostData["item_id"]); - if (preview) - { - LLSD errors; - errors.append(LLTrans::getString("UploadFailed") + content["message"].asString()); - preview->callbackLSLCompileFailed(errors); - } - } - - // remove the "Uploading..." message - LLUploadDialog::modalUploadFinished(); - - LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); - if (floater_snapshot) - { - floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", false).with("msg", "inventory"))); - } - - const std::string& reason = content["state"].asStringRef(); - // deal with L$ errors - if (reason == "insufficient funds") - { - S32 price = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - LLStringUtil::format_map_t args; - args["AMOUNT"] = llformat("%d", price); - LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("uploading_costs", args), price ); - } - else - { - LLSD args; - args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); - args["REASON"] = content["message"].asString(); - LLNotificationsUtil::add("CannotUploadReason", args); - } -} - -void LLAssetUploadResponder::uploadComplete(const LLSD& content) -{ -} - -#if 0 -LLNewAgentInventoryResponder::LLNewAgentInventoryResponder( - const LLSD& post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type) - : LLAssetUploadResponder(post_data, vfile_id, asset_type) -{ -} - -LLNewAgentInventoryResponder::LLNewAgentInventoryResponder( - const LLSD& post_data, - const std::string& file_name, - LLAssetType::EType asset_type) - : LLAssetUploadResponder(post_data, file_name, asset_type) -{ -} - -// virtual -void LLNewAgentInventoryResponder::httpFailure() -{ - LLAssetUploadResponder::httpFailure(); - //LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, LLUUID(), FALSE); -} - - -//virtual -void LLNewAgentInventoryResponder::uploadFailure(const LLSD& content) -{ - LLAssetUploadResponder::uploadFailure(content); - - //LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], FALSE); -} - -//virtual -void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) -{ - LL_DEBUGS() << "LLNewAgentInventoryResponder::result from capabilities" << LL_ENDL; - - //std::ostringstream llsdxml; - //LLSDSerialize::toXML(content, llsdxml); - //LL_INFOS() << "upload complete content:\n " << llsdxml.str() << LL_ENDL; - - LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString()); - LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString()); - S32 expected_upload_cost = 0; - - // Update L$ and ownership credit information - // since it probably changed on the server - if (asset_type == LLAssetType::AT_TEXTURE || - asset_type == LLAssetType::AT_SOUND || - asset_type == LLAssetType::AT_ANIMATION || - asset_type == LLAssetType::AT_MESH) - { - expected_upload_cost = - LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); - } - - on_new_single_inventory_upload_complete( - asset_type, - inventory_type, - mPostData["asset_type"].asString(), - mPostData["folder_id"].asUUID(), - mPostData["name"], - mPostData["description"], - content, - expected_upload_cost); - - // continue uploading for bulk uploads - - // *FIX: This is a pretty big hack. What this does is check the - // file picker if there are any more pending uploads. If so, - // upload that file. - std::string next_file = LLFilePicker::instance().getNextFile(); - if(!next_file.empty()) - { - std::string name = gDirUtilp->getBaseFileName(next_file, true); - - std::string asset_name = name; - LLStringUtil::replaceNonstandardASCII( asset_name, '?' ); - LLStringUtil::replaceChar(asset_name, '|', '?'); - LLStringUtil::stripNonprintable(asset_name); - LLStringUtil::trim(asset_name); - - // Continuing the horrible hack above, we need to extract the originally requested permissions data, if any, - // and use them for each next file to be uploaded. Note the requested perms are not the same as the - U32 everyone_perms = - content.has("new_everyone_mask") ? - content["new_everyone_mask"].asInteger() : - PERM_NONE; - - U32 group_perms = - content.has("new_group_mask") ? - content["new_group_mask"].asInteger() : - PERM_NONE; - - U32 next_owner_perms = - content.has("new_next_owner_mask") ? - content["new_next_owner_mask"].asInteger() : - PERM_NONE; - - std::string display_name = LLStringUtil::null; - LLAssetStorage::LLStoreAssetCallback callback = NULL; - void *userdata = NULL; - - upload_new_resource( - next_file, - asset_name, - asset_name, - 0, - LLFolderType::FT_NONE, - LLInventoryType::IT_NONE, - next_owner_perms, - group_perms, - everyone_perms, - display_name, - callback, - LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(), - userdata); - } - - //LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], TRUE); -} -#endif - -#if 0 -LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder( - const LLSD& post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type) - : LLAssetUploadResponder(post_data, vfile_id, asset_type) -{ -} - -LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder( - const LLSD& post_data, - const std::string& file_name, - LLAssetType::EType asset_type) - : LLAssetUploadResponder(post_data, file_name, asset_type) -{ -} - -//virtual -void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content) -{ - LL_INFOS() << "LLUpdateAgentInventoryResponder::result from capabilities" << LL_ENDL; - LLUUID item_id = mPostData["item_id"]; - - LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(item_id); - if(!item) - { - LL_WARNS() << "Inventory item for " << mVFileID - << " is no longer in agent inventory." << LL_ENDL; - return; - } - - // Update viewer inventory item - LLPointer new_item = new LLViewerInventoryItem(item); - new_item->setAssetUUID(content["new_asset"].asUUID()); - gInventory.updateItem(new_item); - gInventory.notifyObservers(); - - LL_INFOS() << "Inventory item " << item->getName() << " saved into " - << content["new_asset"].asString() << LL_ENDL; - - LLInventoryType::EType inventory_type = new_item->getInventoryType(); - switch(inventory_type) - { - case LLInventoryType::IT_NOTECARD: - { - // Update the UI with the new asset. - LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance("preview_notecard", LLSD(item_id)); - if(nc) - { - // *HACK: we have to delete the asset in the VFS so - // that the viewer will redownload it. This is only - // really necessary if the asset had to be modified by - // the uploader, so this can be optimized away in some - // cases. A better design is to have a new uuid if the - // script actually changed the asset. - if(nc->hasEmbeddedInventory()) - { - gVFS->removeFile(content["new_asset"].asUUID(), LLAssetType::AT_NOTECARD); - } - nc->refreshFromInventory(new_item->getUUID()); - } - break; - } - case LLInventoryType::IT_LSL: - { - // Find our window and close it if requested. - LLPreviewLSL* preview = LLFloaterReg::findTypedInstance("preview_script", LLSD(item_id)); - if (preview) - { - // Bytecode save completed - if (content["compiled"]) - { - preview->callbackLSLCompileSucceeded(); - } - else - { - preview->callbackLSLCompileFailed(content["errors"]); - } - } - break; - } - - case LLInventoryType::IT_GESTURE: - { - // If this gesture is active, then we need to update the in-memory - // active map with the new pointer. - if (LLGestureMgr::instance().isGestureActive(item_id)) - { - LLUUID asset_id = new_item->getAssetUUID(); - LLGestureMgr::instance().replaceGesture(item_id, asset_id); - gInventory.notifyObservers(); - } - - //gesture will have a new asset_id - LLPreviewGesture* previewp = LLFloaterReg::findTypedInstance("preview_gesture", LLSD(item_id)); - if(previewp) - { - previewp->onUpdateSucceeded(); - } - - break; - } - case LLInventoryType::IT_WEARABLE: - default: - break; - } -} -#endif - -#if 0 -LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type) -: LLAssetUploadResponder(post_data, vfile_id, asset_type) -{ -} - -LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, - const std::string& file_name, - LLAssetType::EType asset_type) -: LLAssetUploadResponder(post_data, file_name, asset_type) -{ -} - -LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, - const std::string& file_name, - const LLUUID& queue_id, - LLAssetType::EType asset_type) -: LLAssetUploadResponder(post_data, file_name, asset_type), mQueueId(queue_id) -{ -} - -//virtual -void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content) -{ - LL_INFOS() << "LLUpdateTaskInventoryResponder::result from capabilities" << LL_ENDL; - LLUUID item_id = mPostData["item_id"]; - LLUUID task_id = mPostData["task_id"]; - - dialog_refresh_all(); - - switch(mAssetType) - { - case LLAssetType::AT_NOTECARD: - { - // Update the UI with the new asset. - LLPreviewNotecard* nc = LLFloaterReg::findTypedInstance("preview_notecard", LLSD(item_id)); - if(nc) - { - // *HACK: we have to delete the asset in the VFS so - // that the viewer will redownload it. This is only - // really necessary if the asset had to be modified by - // the uploader, so this can be optimized away in some - // cases. A better design is to have a new uuid if the - // script actually changed the asset. - if(nc->hasEmbeddedInventory()) - { - gVFS->removeFile(content["new_asset"].asUUID(), - LLAssetType::AT_NOTECARD); - } - nc->setAssetId(content["new_asset"].asUUID()); - nc->refreshFromInventory(); - } - break; - } - case LLAssetType::AT_LSL_TEXT: - { - if(mQueueId.notNull()) - { - LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance("compile_queue", mQueueId); - if(NULL != queue) - { - queue->removeItemByItemID(item_id); - } - } - else - { - LLSD floater_key; - floater_key["taskid"] = task_id; - floater_key["itemid"] = item_id; - LLLiveLSLEditor* preview = LLFloaterReg::findTypedInstance("preview_scriptedit", floater_key); - if (preview) - { - // Bytecode save completed - if (content["compiled"]) - { - preview->callbackLSLCompileSucceeded(task_id, item_id, mPostData["is_script_running"]); - } - else - { - preview->callbackLSLCompileFailed(content["errors"]); - } - } - } - break; - } - default: - break; - } -} -#endif - -#if 0 -///////////////////////////////////////////////////// -// LLNewAgentInventoryVariablePriceResponder::Impl // -///////////////////////////////////////////////////// -class LLNewAgentInventoryVariablePriceResponder::Impl -{ -public: - Impl( - const LLUUID& vfile_id, - LLAssetType::EType asset_type, - const LLSD& inventory_data) : - mVFileID(vfile_id), - mAssetType(asset_type), - mInventoryData(inventory_data), - mFileName("") - { - if (!gVFS->getExists(vfile_id, asset_type)) - { - LL_WARNS() - << "LLAssetUploadResponder called with nonexistant " - << "vfile_id " << vfile_id << LL_ENDL; - mVFileID.setNull(); - mAssetType = LLAssetType::AT_NONE; - } - } - - Impl( - const std::string& file_name, - LLAssetType::EType asset_type, - const LLSD& inventory_data) : - mFileName(file_name), - mAssetType(asset_type), - mInventoryData(inventory_data) - { - mVFileID.setNull(); - } - - std::string getFilenameOrIDString() const - { - return (mFileName.empty() ? mVFileID.asString() : mFileName); - } - - LLUUID getVFileID() const - { - return mVFileID; - } - - std::string getFilename() const - { - return mFileName; - } - - LLAssetType::EType getAssetType() const - { - return mAssetType; - } - - LLInventoryType::EType getInventoryType() const - { - return LLInventoryType::lookup( - mInventoryData["inventory_type"].asString()); - } - - std::string getInventoryTypeString() const - { - return mInventoryData["inventory_type"].asString(); - } - - LLUUID getFolderID() const - { - return mInventoryData["folder_id"].asUUID(); - } - - std::string getItemName() const - { - return mInventoryData["name"].asString(); - } - - std::string getItemDescription() const - { - return mInventoryData["description"].asString(); - } - - void displayCannotUploadReason(const std::string& reason) - { - LLSD args; - args["FILE"] = getFilenameOrIDString(); - args["REASON"] = reason; - - - LLNotificationsUtil::add("CannotUploadReason", args); - LLUploadDialog::modalUploadFinished(); - } - - void onApplicationLevelError(const LLSD& error) - { - static const std::string _IDENTIFIER = "identifier"; - - static const std::string _INSUFFICIENT_FUNDS = - "NewAgentInventory_InsufficientLindenDollarBalance"; - static const std::string _MISSING_REQUIRED_PARAMETER = - "NewAgentInventory_MissingRequiredParamater"; - static const std::string _INVALID_REQUEST_BODY = - "NewAgentInventory_InvalidRequestBody"; - static const std::string _RESOURCE_COST_DIFFERS = - "NewAgentInventory_ResourceCostDiffers"; - - static const std::string _MISSING_PARAMETER = "missing_parameter"; - static const std::string _INVALID_PARAMETER = "invalid_parameter"; - static const std::string _MISSING_RESOURCE = "missing_resource"; - static const std::string _INVALID_RESOURCE = "invalid_resource"; - - // TODO* Add the other error_identifiers - - std::string error_identifier = error[_IDENTIFIER].asString(); - - // TODO*: Pull these user visible strings from an xml file - // to be localized - if ( _INSUFFICIENT_FUNDS == error_identifier ) - { - displayCannotUploadReason("You do not have a sufficient L$ balance to complete this upload."); - } - else if ( _MISSING_REQUIRED_PARAMETER == error_identifier ) - { - // Missing parameters - if (error.has(_MISSING_PARAMETER) ) - { - std::string message = - "Upload request was missing required parameter '[P]'"; - LLStringUtil::replaceString( - message, - "[P]", - error[_MISSING_PARAMETER].asString()); - - displayCannotUploadReason(message); - } - else - { - std::string message = - "Upload request was missing a required parameter"; - displayCannotUploadReason(message); - } - } - else if ( _INVALID_REQUEST_BODY == error_identifier ) - { - // Invalid request body, check to see if - // a particular parameter was invalid - if ( error.has(_INVALID_PARAMETER) ) - { - std::string message = "Upload parameter '[P]' is invalid."; - LLStringUtil::replaceString( - message, - "[P]", - error[_INVALID_PARAMETER].asString()); - - // See if the server also responds with what resource - // is missing. - if ( error.has(_MISSING_RESOURCE) ) - { - message += "\nMissing resource '[R]'."; - - LLStringUtil::replaceString( - message, - "[R]", - error[_MISSING_RESOURCE].asString()); - } - else if ( error.has(_INVALID_RESOURCE) ) - { - message += "\nInvalid resource '[R]'."; - - LLStringUtil::replaceString( - message, - "[R]", - error[_INVALID_RESOURCE].asString()); - } - - displayCannotUploadReason(message); - } - else - { - std::string message = "Upload request was malformed"; - displayCannotUploadReason(message); - } - } - else if ( _RESOURCE_COST_DIFFERS == error_identifier ) - { - displayCannotUploadReason("The resource cost associated with this upload is not consistent with the server."); - } - else - { - displayCannotUploadReason("Unknown Error"); - } - } - - void onTransportError() - { - displayCannotUploadReason( - "The server is experiencing unexpected difficulties."); - } - - void onTransportError(const LLSD& error) - { - static const std::string _IDENTIFIER = "identifier"; - - static const std::string _SERVER_ERROR_AFTER_CHARGE = - "NewAgentInventory_ServerErrorAfterCharge"; - - std::string error_identifier = error[_IDENTIFIER].asString(); - - // TODO*: Pull the user visible strings from an xml file - // to be localized - - if ( _SERVER_ERROR_AFTER_CHARGE == error_identifier ) - { - displayCannotUploadReason( - "The server is experiencing unexpected difficulties. You may have been charged for the upload."); - } - else - { - displayCannotUploadReason( - "The server is experiencing unexpected difficulties."); - } - } - - bool uploadConfirmationCallback( - const LLSD& notification, - const LLSD& response, - LLPointer responder) - { - S32 option; - std::string confirmation_url; - - option = LLNotificationsUtil::getSelectedOption( - notification, - response); - - confirmation_url = - notification["payload"]["confirmation_url"].asString(); - - // Yay! We are confirming or cancelling our upload - switch(option) - { - case 0: - { - confirmUpload(confirmation_url, responder); - } - break; - case 1: - default: - break; - } - - return false; - } - - void confirmUpload( - const std::string& confirmation_url, - LLPointer responder) - { - if ( getFilename().empty() ) - { - // we have no filename, use virtual file ID instead - LLHTTPClient::postFile( - confirmation_url, - getVFileID(), - getAssetType(), - responder); - } - else - { - LLHTTPClient::postFile( - confirmation_url, - getFilename(), - responder); - } - } - - -private: - std::string mFileName; - - LLSD mInventoryData; - LLAssetType::EType mAssetType; - LLUUID mVFileID; -}; - -/////////////////////////////////////////////// -// LLNewAgentInventoryVariablePriceResponder // -/////////////////////////////////////////////// -LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder( - const LLUUID& vfile_id, - LLAssetType::EType asset_type, - const LLSD& inventory_info) -{ - mImpl = new Impl( - vfile_id, - asset_type, - inventory_info); -} - -LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder( - const std::string& file_name, - LLAssetType::EType asset_type, - const LLSD& inventory_info) -{ - mImpl = new Impl( - file_name, - asset_type, - inventory_info); -} - -LLNewAgentInventoryVariablePriceResponder::~LLNewAgentInventoryVariablePriceResponder() -{ - delete mImpl; -} - -void LLNewAgentInventoryVariablePriceResponder::httpFailure() -{ - const LLSD& content = getContent(); - LL_WARNS("Upload") << dumpResponse() << LL_ENDL; - - static const std::string _ERROR = "error"; - if ( content.has(_ERROR) ) - { - mImpl->onTransportError(content[_ERROR]); - } - else - { - mImpl->onTransportError(); - } -} - -void LLNewAgentInventoryVariablePriceResponder::httpSuccess() -{ - const LLSD& content = getContent(); - if (!content.isMap()) - { - failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); - return; - } - // Parse out application level errors and the appropriate - // responses for them - static const std::string _ERROR = "error"; - static const std::string _STATE = "state"; - - static const std::string _COMPLETE = "complete"; - static const std::string _CONFIRM_UPLOAD = "confirm_upload"; - - static const std::string _UPLOAD_PRICE = "upload_price"; - static const std::string _RESOURCE_COST = "resource_cost"; - static const std::string _RSVP = "rsvp"; - - // Check for application level errors - if ( content.has(_ERROR) ) - { - LL_WARNS("Upload") << dumpResponse() << LL_ENDL; - onApplicationLevelError(content[_ERROR]); - return; - } - - std::string state = content[_STATE]; - LLAssetType::EType asset_type = mImpl->getAssetType(); - - if ( _COMPLETE == state ) - { - // rename file in VFS with new asset id - if (mImpl->getFilename().empty()) - { - // rename the file in the VFS to the actual asset id - // LL_INFOS() << "Changing uploaded asset UUID to " << content["new_asset"].asUUID() << LL_ENDL; - gVFS->renameFile( - mImpl->getVFileID(), - asset_type, - content["new_asset"].asUUID(), - asset_type); - } - - on_new_single_inventory_upload_complete( - asset_type, - mImpl->getInventoryType(), - mImpl->getInventoryTypeString(), - mImpl->getFolderID(), - mImpl->getItemName(), - mImpl->getItemDescription(), - content, - content[_UPLOAD_PRICE].asInteger()); - - // TODO* Add bulk (serial) uploading or add - // a super class of this that does so - } - else if ( _CONFIRM_UPLOAD == state ) - { - showConfirmationDialog( - content[_UPLOAD_PRICE].asInteger(), - content[_RESOURCE_COST].asInteger(), - content[_RSVP].asString()); - } - else - { - LL_WARNS("Upload") << dumpResponse() << LL_ENDL; - onApplicationLevelError(""); - } -} - -void LLNewAgentInventoryVariablePriceResponder::onApplicationLevelError( - const LLSD& error) -{ - mImpl->onApplicationLevelError(error); -} - -void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog( - S32 upload_price, - S32 resource_cost, - const std::string& confirmation_url) -{ - if ( 0 == upload_price ) - { - // don't show confirmation dialog for free uploads, I mean, - // they're free! - - // The creating of a new instrusive_ptr(this) - // creates a new boost::intrusive_ptr - // which is a copy of this. This code is required because - // 'this' is always of type Class* and not the intrusive_ptr, - // and thus, a reference to 'this' is not registered - // by using just plain 'this'. - - // Since LLNewAgentInventoryVariablePriceResponder is a - // reference counted class, it is possible (since the - // reference to a plain 'this' would be missed here) that, - // when using plain ol' 'this', that this object - // would be deleted before the callback is triggered - // and cause sadness. - mImpl->confirmUpload( - confirmation_url, - LLPointer(this)); - } - else - { - LLSD substitutions; - LLSD payload; - - substitutions["PRICE"] = upload_price; - - payload["confirmation_url"] = confirmation_url; - - // The creating of a new instrusive_ptr(this) - // creates a new boost::intrusive_ptr - // which is a copy of this. This code is required because - // 'this' is always of type Class* and not the intrusive_ptr, - // and thus, a reference to 'this' is not registered - // by using just plain 'this'. - - // Since LLNewAgentInventoryVariablePriceResponder is a - // reference counted class, it is possible (since the - // reference to a plain 'this' would be missed here) that, - // when using plain ol' 'this', that this object - // would be deleted before the callback is triggered - // and cause sadness. - LLNotificationsUtil::add( - "UploadCostConfirmation", - substitutions, - payload, - boost::bind( - &LLNewAgentInventoryVariablePriceResponder::Impl::uploadConfirmationCallback, - mImpl, - _1, - _2, - LLPointer(this))); - } -} -#endif - diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h deleted file mode 100755 index d3457ce450..0000000000 --- a/indra/newview/llassetuploadresponders.h +++ /dev/null @@ -1,158 +0,0 @@ -/** - * @file llassetuploadresponders.h - * @brief Processes responses received for asset upload requests. - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLASSETUPLOADRESPONDER_H -#define LL_LLASSETUPLOADRESPONDER_H - -#include "llhttpclient.h" - -// Abstract class for supporting asset upload -// via capabilities -class LLAssetUploadResponder : public LLHTTPClient::Responder -{ -protected: - LOG_CLASS(LLAssetUploadResponder); -public: - LLAssetUploadResponder(const LLSD& post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type); - LLAssetUploadResponder(const LLSD& post_data, - const std::string& file_name, - LLAssetType::EType asset_type); - ~LLAssetUploadResponder(); - -protected: - virtual void httpFailure(); - virtual void httpSuccess(); - -public: - virtual void uploadUpload(const LLSD& content); - virtual void uploadComplete(const LLSD& content); - virtual void uploadFailure(const LLSD& content); - -protected: - LLSD mPostData; - LLAssetType::EType mAssetType; - LLUUID mVFileID; - std::string mFileName; -}; - -#if 0 -// TODO*: Remove this once deprecated -class LLNewAgentInventoryResponder : public LLAssetUploadResponder -{ - LOG_CLASS(LLNewAgentInventoryResponder); -public: - LLNewAgentInventoryResponder( - const LLSD& post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type); - LLNewAgentInventoryResponder( - const LLSD& post_data, - const std::string& file_name, - LLAssetType::EType asset_type); - virtual void uploadComplete(const LLSD& content); - virtual void uploadFailure(const LLSD& content); -protected: - virtual void httpFailure(); -}; -#endif -#if 0 -// A base class which goes through and performs some default -// actions for variable price uploads. If more specific actions -// are needed (such as different confirmation messages, etc.) -// the functions onApplicationLevelError and showConfirmationDialog. -class LLNewAgentInventoryVariablePriceResponder : - public LLHTTPClient::Responder -{ - LOG_CLASS(LLNewAgentInventoryVariablePriceResponder); -public: - LLNewAgentInventoryVariablePriceResponder( - const LLUUID& vfile_id, - LLAssetType::EType asset_type, - const LLSD& inventory_info); - - LLNewAgentInventoryVariablePriceResponder( - const std::string& file_name, - LLAssetType::EType asset_type, - const LLSD& inventory_info); - virtual ~LLNewAgentInventoryVariablePriceResponder(); - -private: - /* virtual */ void httpFailure(); - /* virtual */ void httpSuccess(); - -public: - virtual void onApplicationLevelError( - const LLSD& error); - virtual void showConfirmationDialog( - S32 upload_price, - S32 resource_cost, - const std::string& confirmation_url); - -private: - class Impl; - Impl* mImpl; -}; -#endif - -#if 0 -class LLUpdateAgentInventoryResponder : public LLAssetUploadResponder -{ -public: - LLUpdateAgentInventoryResponder(const LLSD& post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type); - LLUpdateAgentInventoryResponder(const LLSD& post_data, - const std::string& file_name, - LLAssetType::EType asset_type); - virtual void uploadComplete(const LLSD& content); -}; -#endif - -#if 0 -class LLUpdateTaskInventoryResponder : public LLAssetUploadResponder -{ -public: - LLUpdateTaskInventoryResponder(const LLSD& post_data, - const LLUUID& vfile_id, - LLAssetType::EType asset_type); - LLUpdateTaskInventoryResponder(const LLSD& post_data, - const std::string& file_name, - LLAssetType::EType asset_type); - LLUpdateTaskInventoryResponder(const LLSD& post_data, - const std::string& file_name, - const LLUUID& queue_id, - LLAssetType::EType asset_type); - - virtual void uploadComplete(const LLSD& content); - -private: - LLUUID mQueueId; -}; -#endif - -#endif // LL_LLASSETUPLOADRESPONDER_H diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index c4b0b96d4c..24e662ee50 100755 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -37,7 +37,6 @@ #include "llcompilequeue.h" #include "llagent.h" -#include "llassetuploadresponders.h" #include "llchat.h" #include "llfloaterreg.h" #include "llviewerwindow.h" diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index b38362e180..d8f5f27681 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -77,7 +77,6 @@ #include "lluictrlfactory.h" #include "llviewernetwork.h" -#include "llassetuploadresponders.h" #include "llagentui.h" #include "lltrans.h" diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index d6aaf18cb7..c34d04c98e 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -72,6 +72,10 @@ #include "bufferstream.h" #include "llfasttimer.h" #include "llcorehttputil.h" +#include "llstatusbar.h" +#include "llinventorypanel.h" +#include "lluploaddialog.h" +#include "llfloaterreg.h" #include "boost/lexical_cast.hpp" @@ -412,6 +416,17 @@ static unsigned int metrics_teleport_start_count = 0; boost::signals2::connection metrics_teleport_started_signal; static void teleport_started(); +void on_new_single_inventory_upload_complete( + LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + const std::string inventory_type_string, + const LLUUID& item_folder_id, + const std::string& item_name, + const std::string& item_description, + const LLSD& server_response, + S32 upload_price); + + //get the number of bytes resident in memory for given volume U32 get_volume_memory_size(const LLVolume* volume) { @@ -4567,3 +4582,122 @@ void teleport_started() LLMeshRepository::metricsStart(); } + +void on_new_single_inventory_upload_complete( + LLAssetType::EType asset_type, + LLInventoryType::EType inventory_type, + const std::string inventory_type_string, + const LLUUID& item_folder_id, + const std::string& item_name, + const std::string& item_description, + const LLSD& server_response, + S32 upload_price) +{ + bool success = false; + + if (upload_price > 0) + { + // this upload costed us L$, update our balance + // and display something saying that it cost L$ + LLStatusBar::sendMoneyBalanceRequest(); + + LLSD args; + args["AMOUNT"] = llformat("%d", upload_price); + LLNotificationsUtil::add("UploadPayment", args); + } + + if (item_folder_id.notNull()) + { + U32 everyone_perms = PERM_NONE; + U32 group_perms = PERM_NONE; + U32 next_owner_perms = PERM_ALL; + if (server_response.has("new_next_owner_mask")) + { + // The server provided creation perms so use them. + // Do not assume we got the perms we asked for in + // since the server may not have granted them all. + everyone_perms = server_response["new_everyone_mask"].asInteger(); + group_perms = server_response["new_group_mask"].asInteger(); + next_owner_perms = server_response["new_next_owner_mask"].asInteger(); + } + else + { + // The server doesn't provide creation perms + // so use old assumption-based perms. + if (inventory_type_string != "snapshot") + { + next_owner_perms = PERM_MOVE | PERM_TRANSFER; + } + } + + LLPermissions new_perms; + new_perms.init( + gAgent.getID(), + gAgent.getID(), + LLUUID::null, + LLUUID::null); + + new_perms.initMasks( + PERM_ALL, + PERM_ALL, + everyone_perms, + group_perms, + next_owner_perms); + + U32 inventory_item_flags = 0; + if (server_response.has("inventory_flags")) + { + inventory_item_flags = (U32)server_response["inventory_flags"].asInteger(); + if (inventory_item_flags != 0) + { + LL_INFOS() << "inventory_item_flags " << inventory_item_flags << LL_ENDL; + } + } + S32 creation_date_now = time_corrected(); + LLPointer item = new LLViewerInventoryItem( + server_response["new_inventory_item"].asUUID(), + item_folder_id, + new_perms, + server_response["new_asset"].asUUID(), + asset_type, + inventory_type, + item_name, + item_description, + LLSaleInfo::DEFAULT, + inventory_item_flags, + creation_date_now); + + gInventory.updateItem(item); + gInventory.notifyObservers(); + success = true; + + // Show the preview panel for textures and sounds to let + // user know that the image (or snapshot) arrived intact. + LLInventoryPanel* panel = LLInventoryPanel::getActiveInventoryPanel(); + if (panel) + { + LLFocusableElement* focus = gFocusMgr.getKeyboardFocus(); + + panel->setSelection( + server_response["new_inventory_item"].asUUID(), + TAKE_FOCUS_NO); + + // restore keyboard focus + gFocusMgr.setKeyboardFocus(focus); + } + } + else + { + LL_WARNS() << "Can't find a folder to put it in" << LL_ENDL; + } + + // remove the "Uploading..." message + LLUploadDialog::modalUploadFinished(); + + // Let the Snapshot floater know we have finished uploading a snapshot to inventory. + LLFloater* floater_snapshot = LLFloaterReg::findInstance("snapshot"); + if (asset_type == LLAssetType::AT_TEXTURE && floater_snapshot) + { + floater_snapshot->notify(LLSD().with("set-finished", LLSD().with("ok", success).with("msg", "inventory"))); + } +} diff --git a/indra/newview/llpostcard.cpp b/indra/newview/llpostcard.cpp index 4e34ec912e..2e639b56eb 100755 --- a/indra/newview/llpostcard.cpp +++ b/indra/newview/llpostcard.cpp @@ -36,7 +36,6 @@ #include "llagent.h" #include "llassetstorage.h" -#include "llassetuploadresponders.h" #include "llviewerassetupload.h" /////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 2604eb1840..ff9a70d05c 100755 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -31,7 +31,6 @@ #include "llanimstatelabels.h" #include "llanimationstates.h" #include "llappviewer.h" // gVFS -#include "llassetuploadresponders.h" #include "llcheckboxctrl.h" #include "llcombobox.h" #include "lldatapacker.h" diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 9273e06d65..2c609d902c 100755 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -31,7 +31,6 @@ #include "llinventory.h" #include "llagent.h" -#include "llassetuploadresponders.h" #include "lldraghandle.h" #include "llviewerwindow.h" #include "llbutton.h" diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 2f09214dd6..11a503e71f 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -29,7 +29,6 @@ #include "llpreviewscript.h" #include "llassetstorage.h" -#include "llassetuploadresponders.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 904fa7fcbe..782a27a846 100755 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -65,7 +65,6 @@ #include "llviewerassetupload.h" // linden libraries -#include "llassetuploadresponders.h" #include "lleconomy.h" #include "llhttpclient.h" #include "llnotificationsutil.h" diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 0f8fa56b52..6941b4dc0e 100755 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -70,16 +70,6 @@ void assign_defaults_and_show_upload_message( const std::string& display_name, std::string& description); -void on_new_single_inventory_upload_complete( - LLAssetType::EType asset_type, - LLInventoryType::EType inventory_type, - const std::string inventory_type_string, - const LLUUID& item_folder_id, - const std::string& item_name, - const std::string& item_description, - const LLSD& server_response, - S32 upload_price); - class LLFilePickerThread : public LLThread { //multi-threaded file picker (runs system specific file picker in background and calls "notify" from main thread) public: -- cgit v1.3 From 96e343b49b0b5a0951ffab0beb2e1d09c37bbdc5 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Tue, 1 Sep 2015 16:13:52 -0700 Subject: MAINT-5575: Convert the Experience cache into a coro based singleton. --HG-- branch : MAINT-5575 --- indra/llmessage/CMakeLists.txt | 2 + indra/llmessage/llcoproceduremanager.cpp | 414 +++++++++++++++ indra/llmessage/llcoproceduremanager.h | 98 ++++ indra/llmessage/llexperiencecache.cpp | 569 ++++++++++----------- indra/llmessage/llexperiencecache.h | 99 ++-- indra/llui/CMakeLists.txt | 2 + indra/llui/llurlentry.cpp | 4 +- indra/newview/CMakeLists.txt | 2 - indra/newview/llagent.cpp | 9 + indra/newview/llagent.h | 3 + indra/newview/llappviewer.cpp | 57 +-- indra/newview/llappviewer.h | 4 - indra/newview/llcoproceduremanager.cpp | 406 --------------- indra/newview/llcoproceduremanager.h | 87 ---- indra/newview/llexperienceassociationresponder.cpp | 2 +- indra/newview/llfloaterexperienceprofile.cpp | 10 +- indra/newview/llfloaterreporter.cpp | 2 +- indra/newview/llpanelexperiencelisteditor.cpp | 2 +- indra/newview/llpanelexperiencelog.cpp | 4 +- indra/newview/llpanelexperiencepicker.cpp | 2 +- indra/newview/llpreviewscript.cpp | 6 +- indra/newview/llstartup.cpp | 7 +- indra/newview/llviewermessage.cpp | 2 +- 23 files changed, 897 insertions(+), 896 deletions(-) create mode 100644 indra/llmessage/llcoproceduremanager.cpp create mode 100644 indra/llmessage/llcoproceduremanager.h delete mode 100644 indra/newview/llcoproceduremanager.cpp delete mode 100644 indra/newview/llcoproceduremanager.h (limited to 'indra/newview/llfloaterreporter.cpp') diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index 9739f7c607..12fc1bbcfc 100755 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -40,6 +40,7 @@ set(llmessage_SOURCE_FILES llchainio.cpp llcircuit.cpp llclassifiedflags.cpp + llcoproceduremanager.cpp llcorehttputil.cpp llcurl.cpp lldatapacker.cpp @@ -128,6 +129,7 @@ set(llmessage_HEADER_FILES llcipher.h llcircuit.h llclassifiedflags.h + llcoproceduremanager.h llcorehttputil.h llcurl.h lldatapacker.h diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp new file mode 100644 index 0000000000..062f2e6e42 --- /dev/null +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -0,0 +1,414 @@ +/** +* @file LLCoprocedurePool.cpp +* @author Rider Linden +* @brief Singleton class for managing asset uploads to the sim. +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#include "linden_common.h" +#include "llcoproceduremanager.h" + +//========================================================================= +// Map of pool sizes for known pools +static std::map DefaultPoolSizes; + +// *TODO$: When C++11 this can be initialized here as follows: +// = {{"AIS", 25}, {"Upload", 1}} + +#define DEFAULT_POOL_SIZE 5 + +//========================================================================= +class LLCoprocedurePool: private boost::noncopyable +{ +public: + typedef LLCoprocedureManager::CoProcedure_t CoProcedure_t; + + LLCoprocedurePool(const std::string &name, size_t size); + virtual ~LLCoprocedurePool(); + + /// Places the coprocedure on the queue for processing. + /// + /// @param name Is used for debugging and should identify this coroutine. + /// @param proc Is a bound function to be executed + /// + /// @return This method returns a UUID that can be used later to cancel execution. + LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc); + + /// Cancel a coprocedure. If the coprocedure is already being actively executed + /// this method calls cancelYieldingOperation() on the associated HttpAdapter + /// If it has not yet been dequeued it is simply removed from the queue. + bool cancelCoprocedure(const LLUUID &id); + + /// Requests a shutdown of the upload manager. Passing 'true' will perform + /// an immediate kill on the upload coroutine. + void shutdown(bool hardShutdown = false); + + /// Returns the number of coprocedures in the queue awaiting processing. + /// + inline size_t countPending() const + { + return mPendingCoprocs.size(); + } + + /// Returns the number of coprocedures actively being processed. + /// + inline size_t countActive() const + { + return mActiveCoprocs.size(); + } + + /// Returns the total number of coprocedures either queued or in active processing. + /// + inline size_t count() const + { + return countPending() + countActive(); + } + +private: + struct QueuedCoproc + { + typedef boost::shared_ptr ptr_t; + + QueuedCoproc(const std::string &name, const LLUUID &id, CoProcedure_t proc) : + mName(name), + mId(id), + mProc(proc) + {} + + std::string mName; + LLUUID mId; + CoProcedure_t mProc; + }; + + // we use a deque here rather than std::queue since we want to be able to + // iterate through the queue and potentially erase an entry from the middle. + typedef std::deque CoprocQueue_t; + typedef std::map ActiveCoproc_t; + + std::string mPoolName; + size_t mPoolSize; + CoprocQueue_t mPendingCoprocs; + ActiveCoproc_t mActiveCoprocs; + bool mShutdown; + LLEventStream mWakeupTrigger; + + typedef std::map CoroAdapterMap_t; + LLCore::HttpRequest::policy_t mHTTPPolicy; + + CoroAdapterMap_t mCoroMapping; + + void coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter); + +}; + +//========================================================================= +LLCoprocedureManager::LLCoprocedureManager() +{ + DefaultPoolSizes.insert(std::map::value_type("Upload", 1)); + DefaultPoolSizes.insert(std::map::value_type("AIS", 25)); +} + +LLCoprocedureManager::~LLCoprocedureManager() +{ + +} + +LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::string &poolName) +{ + // Attempt to look up a pool size in the configuration. If found use that + std::string keyName = "PoolSize" + poolName; + int size = 0; + + if (mPropertyQueryFn && !mPropertyQueryFn.empty()) + { + size = mPropertyQueryFn(keyName); + } + + if (size == 0) + { // if not found grab the know default... if there is no known + // default use a reasonable number like 5. + std::map::iterator it = DefaultPoolSizes.find(poolName); + if (it == DefaultPoolSizes.end()) + size = DEFAULT_POOL_SIZE; + else + size = (*it).second; + + if (mPropertyDefineFn && !mPropertyDefineFn.empty()) + mPropertyDefineFn(keyName, size, "Coroutine Pool size for " + poolName); + LL_WARNS() << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL; + } + + poolPtr_t pool = poolPtr_t(new LLCoprocedurePool(poolName, size)); + mPoolMap.insert(poolMap_t::value_type(poolName, pool)); + + return pool; +} + +//------------------------------------------------------------------------- +LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc) +{ + // Attempt to find the pool and enqueue the procedure. If the pool does + // not exist, create it. + poolPtr_t targetPool; + poolMap_t::iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + { + targetPool = initializePool(pool); + } + else + { + targetPool = (*it).second; + } + + if (!targetPool) + { + LL_WARNS() << "LLCoprocedureManager unable to create coprocedure pool named \"" << pool << "\"" << LL_ENDL; + return LLUUID::null; + } + + return targetPool->enqueueCoprocedure(name, proc); +} + +void LLCoprocedureManager::cancelCoprocedure(const LLUUID &id) +{ + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + if ((*it).second->cancelCoprocedure(id)) + return; + } + LL_INFOS() << "Coprocedure not found." << LL_ENDL; +} + +void LLCoprocedureManager::shutdown(bool hardShutdown) +{ + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + (*it).second->shutdown(hardShutdown); + } + mPoolMap.clear(); +} + +void LLCoprocedureManager::setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn) +{ + mPropertyQueryFn = queryfn; + mPropertyDefineFn = updatefn; +} + +//------------------------------------------------------------------------- +size_t LLCoprocedureManager::countPending() const +{ + size_t count = 0; + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + count += (*it).second->countPending(); + } + return count; +} + +size_t LLCoprocedureManager::countPending(const std::string &pool) const +{ + poolMap_t::const_iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + return 0; + return (*it).second->countPending(); +} + +size_t LLCoprocedureManager::countActive() const +{ + size_t count = 0; + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + count += (*it).second->countActive(); + } + return count; +} + +size_t LLCoprocedureManager::countActive(const std::string &pool) const +{ + poolMap_t::const_iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + return 0; + return (*it).second->countActive(); +} + +size_t LLCoprocedureManager::count() const +{ + size_t count = 0; + for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) + { + count += (*it).second->count(); + } + return count; +} + +size_t LLCoprocedureManager::count(const std::string &pool) const +{ + poolMap_t::const_iterator it = mPoolMap.find(pool); + + if (it == mPoolMap.end()) + return 0; + return (*it).second->count(); +} + +//========================================================================= +LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size): + mPoolName(poolName), + mPoolSize(size), + mPendingCoprocs(), + mShutdown(false), + mWakeupTrigger("CoprocedurePool" + poolName, true), + mCoroMapping(), + mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) +{ + for (size_t count = 0; count < mPoolSize; ++count) + { + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter = + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t( + new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy)); + + std::string uploadCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro", + boost::bind(&LLCoprocedurePool::coprocedureInvokerCoro, this, httpAdapter)); + + mCoroMapping.insert(CoroAdapterMap_t::value_type(uploadCoro, httpAdapter)); + } + + LL_INFOS() << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items." << LL_ENDL; + + mWakeupTrigger.post(LLSD()); +} + +LLCoprocedurePool::~LLCoprocedurePool() +{ + shutdown(); +} + +//------------------------------------------------------------------------- +void LLCoprocedurePool::shutdown(bool hardShutdown) +{ + CoroAdapterMap_t::iterator it; + + for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it) + { + if (!(*it).first.empty()) + { + if (hardShutdown) + { + LLCoros::instance().kill((*it).first); + } + } + if ((*it).second) + { + (*it).second->cancelYieldingOperation(); + } + } + + mShutdown = true; + mCoroMapping.clear(); + mPendingCoprocs.clear(); +} + +//------------------------------------------------------------------------- +LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoprocedurePool::CoProcedure_t proc) +{ + LLUUID id(LLUUID::generateNewID()); + + mPendingCoprocs.push_back(QueuedCoproc::ptr_t(new QueuedCoproc(name, id, proc))); + LL_INFOS() << "Coprocedure(" << name << ") enqueued with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + + mWakeupTrigger.post(LLSD()); + + return id; +} + +bool LLCoprocedurePool::cancelCoprocedure(const LLUUID &id) +{ + // first check the active coroutines. If there, remove it and return. + ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(id); + if (itActive != mActiveCoprocs.end()) + { + LL_INFOS() << "Found and canceling active coprocedure with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + (*itActive).second->cancelYieldingOperation(); + mActiveCoprocs.erase(itActive); + return true; + } + + for (CoprocQueue_t::iterator it = mPendingCoprocs.begin(); it != mPendingCoprocs.end(); ++it) + { + if ((*it)->mId == id) + { + LL_INFOS() << "Found and removing queued coroutine(" << (*it)->mName << ") with Id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + mPendingCoprocs.erase(it); + return true; + } + } + + LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found." << " in pool \"" << mPoolName << "\"" << LL_ENDL; + return false; +} + +//------------------------------------------------------------------------- +void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter) +{ + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + + while (!mShutdown) + { + llcoro::waitForEventOn(mWakeupTrigger); + if (mShutdown) + break; + + while (!mPendingCoprocs.empty()) + { + QueuedCoproc::ptr_t coproc = mPendingCoprocs.front(); + mPendingCoprocs.pop_front(); + mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)); + + LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; + + try + { + coproc->mProc(httpAdapter, coproc->mId); + } + catch (std::exception &e) + { + LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() << + " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL; + } + catch (...) + { + LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL; + } + + LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL; + + ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(coproc->mId); + if (itActive != mActiveCoprocs.end()) + { + mActiveCoprocs.erase(itActive); + } + } + } +} diff --git a/indra/llmessage/llcoproceduremanager.h b/indra/llmessage/llcoproceduremanager.h new file mode 100644 index 0000000000..497367b80c --- /dev/null +++ b/indra/llmessage/llcoproceduremanager.h @@ -0,0 +1,98 @@ +/** +* @file llcoproceduremanager.h +* @author Rider Linden +* @brief Singleton class for managing asset uploads to the sim. +* +* $LicenseInfo:firstyear=2015&license=viewerlgpl$ +* Second Life Viewer Source Code +* Copyright (C) 2015, Linden Research, Inc. +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License only. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this library; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +* +* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA +* $/LicenseInfo$ +*/ + +#ifndef LL_COPROCEDURE_MANAGER_H +#define LL_COPROCEDURE_MANAGER_H + +#include "lleventcoro.h" +#include "llcoros.h" +#include "llcorehttputil.h" +#include "lluuid.h" + +class LLCoprocedurePool; + +class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager > +{ + friend class LLSingleton < LLCoprocedureManager > ; + +public: + typedef boost::function SettingQuery_t; + typedef boost::function SettingUpdate_t; + + typedef boost::function CoProcedure_t; + + LLCoprocedureManager(); + virtual ~LLCoprocedureManager(); + + /// Places the coprocedure on the queue for processing. + /// + /// @param name Is used for debugging and should identify this coroutine. + /// @param proc Is a bound function to be executed + /// + /// @return This method returns a UUID that can be used later to cancel execution. + LLUUID enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc); + + /// Cancel a coprocedure. If the coprocedure is already being actively executed + /// this method calls cancelYieldingOperation() on the associated HttpAdapter + /// If it has not yet been dequeued it is simply removed from the queue. + void cancelCoprocedure(const LLUUID &id); + + /// Requests a shutdown of the upload manager. Passing 'true' will perform + /// an immediate kill on the upload coroutine. + void shutdown(bool hardShutdown = false); + + void setPropertyMethods(SettingQuery_t queryfn, SettingUpdate_t updatefn); + + /// Returns the number of coprocedures in the queue awaiting processing. + /// + size_t countPending() const; + size_t countPending(const std::string &pool) const; + + /// Returns the number of coprocedures actively being processed. + /// + size_t countActive() const; + size_t countActive(const std::string &pool) const; + + /// Returns the total number of coprocedures either queued or in active processing. + /// + size_t count() const; + size_t count(const std::string &pool) const; + +private: + + typedef boost::shared_ptr poolPtr_t; + typedef std::map poolMap_t; + + poolMap_t mPoolMap; + + poolPtr_t initializePool(const std::string &poolName); + + SettingQuery_t mPropertyQueryFn; + SettingUpdate_t mPropertyDefineFn; +}; + +#endif diff --git a/indra/llmessage/llexperiencecache.cpp b/indra/llmessage/llexperiencecache.cpp index 34c4210359..36a4fc8823 100644 --- a/indra/llmessage/llexperiencecache.cpp +++ b/indra/llmessage/llexperiencecache.cpp @@ -26,53 +26,51 @@ #include "llexperiencecache.h" #include "llavatarname.h" -#include "llframetimer.h" #include "llhttpclient.h" #include "llsdserialize.h" +#include "llcoros.h" +#include "lleventcoro.h" +#include "lleventfilter.h" +#include "llcoproceduremanager.h" +#include "lldir.h" #include #include -#include "boost/tokenizer.hpp" +#include #include - -typedef std::map KeyMap; -KeyMap privateToPublicKeyMap; - - -std::string sLookupURL; - -typedef std::map pending_queue_t; -pending_queue_t sPendingQueue; - -int sMaximumLookups = 10; - -LLFrameTimer sRequestTimer; - -// Periodically clean out expired entries from the cache -LLFrameTimer sEraseExpiredTimer; - - //========================================================================= namespace LLExperienceCacheImpl { - bool max_age_from_cache_control(const std::string& cache_control, S32 *max_age); void mapKeys(const LLSD& legacyKeys); + F64 getErrorRetryDeltaTime(S32 status, LLSD headers); + bool maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age); + + static const std::string PRIVATE_KEY = "private_id"; + static const std::string EXPERIENCE_ID = "public_id"; + + static const std::string MAX_AGE("max-age"); + static const boost::char_separator EQUALS_SEPARATOR("="); + static const boost::char_separator COMMA_SEPARATOR(","); + + // *TODO$: this seems to be tied to mapKeys which is used by bootstrap.... but I don't think that bootstrap is used. + typedef std::map KeyMap; + KeyMap privateToPublicKeyMap; } //========================================================================= const std::string LLExperienceCache::PRIVATE_KEY = "private_id"; const std::string LLExperienceCache::MISSING = "DoesNotExist"; -const std::string LLExperienceCache::AGENT_ID = "agent_id"; -const std::string LLExperienceCache::GROUP_ID = "group_id"; +const std::string LLExperienceCache::AGENT_ID = "agent_id"; +const std::string LLExperienceCache::GROUP_ID = "group_id"; const std::string LLExperienceCache::EXPERIENCE_ID = "public_id"; const std::string LLExperienceCache::NAME = "name"; const std::string LLExperienceCache::PROPERTIES = "properties"; const std::string LLExperienceCache::EXPIRES = "expiration"; const std::string LLExperienceCache::DESCRIPTION = "description"; const std::string LLExperienceCache::QUOTA = "quota"; -const std::string LLExperienceCache::MATURITY = "maturity"; -const std::string LLExperienceCache::METADATA = "extended_metadata"; +const std::string LLExperienceCache::MATURITY = "maturity"; +const std::string LLExperienceCache::METADATA = "extended_metadata"; const std::string LLExperienceCache::SLURL = "slurl"; // should be in sync with experience-api/experiences/models.py @@ -80,20 +78,51 @@ const int LLExperienceCache::PROPERTY_INVALID = 1 << 0; const int LLExperienceCache::PROPERTY_PRIVILEGED = 1 << 3; const int LLExperienceCache::PROPERTY_GRID = 1 << 4; const int LLExperienceCache::PROPERTY_PRIVATE = 1 << 5; -const int LLExperienceCache::PROPERTY_DISABLED = 1 << 6; -const int LLExperienceCache::PROPERTY_SUSPENDED = 1 << 7; +const int LLExperienceCache::PROPERTY_DISABLED = 1 << 6; +const int LLExperienceCache::PROPERTY_SUSPENDED = 1 << 7; // default values -const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0; +const F64 LLExperienceCache::DEFAULT_EXPIRATION = 600.0; const S32 LLExperienceCache::DEFAULT_QUOTA = 128; // this is megabytes //========================================================================= -LLExperienceCache::LLExperienceCache() +LLExperienceCache::LLExperienceCache(): + mShutdown(false) { } LLExperienceCache::~LLExperienceCache() { + +} + +void LLExperienceCache::initSingleton() +{ + mCacheFileName = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); + + LL_INFOS("ExperienceCache") << "Loading " << mCacheFileName << LL_ENDL; + llifstream cache_stream(mCacheFileName.c_str()); + + if (cache_stream.is_open()) + { + cache_stream >> (*this); + } + + LLCoros::instance().launch("LLExperienceCache::idleCoro", + boost::bind(&LLExperienceCache::idleCoro, this)); + +} + +void LLExperienceCache::cleanup() +{ + LL_INFOS("ExperienceCache") << "Saving " << mCacheFileName << LL_ENDL; + + llofstream cache_stream(mCacheFileName.c_str()); + if (cache_stream.is_open()) + { + cache_stream << (*this); + } + mShutdown = true; } //------------------------------------------------------------------------- @@ -110,18 +139,18 @@ void LLExperienceCache::importFile(std::istream& istr) for (; it != experiences.endMap(); ++it) { public_key.set(it->first); - sCache[public_key] = it->second; + mCache[public_key] = it->second; } - LL_DEBUGS("ExperienceCache") << "importFile() loaded " << sCache.size() << LL_ENDL; + LL_DEBUGS("ExperienceCache") << "importFile() loaded " << mCache.size() << LL_ENDL; } void LLExperienceCache::exportFile(std::ostream& ostr) const { LLSD experiences; - cache_t::const_iterator it = sCache.begin(); - for (; it != sCache.end(); ++it) + cache_t::const_iterator it = mCache.begin(); + for (; it != mCache.end(); ++it) { if (!it->second.has(EXPERIENCE_ID) || it->second[EXPERIENCE_ID].asUUID().isNull() || it->second.has("DoesNotExist") || (it->second.has(PROPERTIES) && it->second[PROPERTIES].asInteger() & PROPERTY_INVALID)) @@ -136,7 +165,7 @@ void LLExperienceCache::exportFile(std::ostream& ostr) const LLSDSerialize::toPrettyXML(data, ostr); } -// *TODO$: Rider: These three functions not seem to be used... it may be useful in testing. +// *TODO$: Rider: This method does not seem to be used... it may be useful in testing. void LLExperienceCache::bootstrap(const LLSD& legacyKeys, int initialExpiration) { LLExperienceCacheImpl::mapKeys(legacyKeys); @@ -166,8 +195,8 @@ LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_i if (private_key.isNull()) return LLUUID::null; - KeyMap::const_iterator it = privateToPublicKeyMap.find(private_key); - if (it == privateToPublicKeyMap.end()) + LLExperienceCacheImpl::KeyMap::const_iterator it = LLExperienceCacheImpl::privateToPublicKeyMap.find(private_key); + if (it == LLExperienceCacheImpl::privateToPublicKeyMap.end()) { if (null_if_not_found) { @@ -182,8 +211,10 @@ LLUUID LLExperienceCache::getExperienceId(const LLUUID& private_key, bool null_i //========================================================================= void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& experience) { - sCache[public_key]=experience; - LLSD & row = sCache[public_key]; + LL_INFOS("ExperienceCache") << "Processing experience \"" << experience[NAME] << "\" with key " << public_key.asString() << LL_ENDL; + + mCache[public_key]=experience; + LLSD & row = mCache[public_key]; if(row.has(EXPIRES)) { @@ -192,233 +223,148 @@ void LLExperienceCache::processExperience(const LLUUID& public_key, const LLSD& if(row.has(EXPERIENCE_ID)) { - sPendingQueue.erase(row[EXPERIENCE_ID].asUUID()); + mPendingQueue.erase(row[EXPERIENCE_ID].asUUID()); } //signal - signal_map_t::iterator sig_it = sSignalMap.find(public_key); - if (sig_it != sSignalMap.end()) + signal_map_t::iterator sig_it = mSignalMap.find(public_key); + if (sig_it != mSignalMap.end()) { signal_ptr signal = sig_it->second; (*signal)(experience); - sSignalMap.erase(public_key); + mSignalMap.erase(public_key); } } const LLExperienceCache::cache_t& LLExperienceCache::getCached() { - return sCache; -} - -void LLExperienceCache::setMaximumLookups(int maximumLookups) -{ - sMaximumLookups = maximumLookups; + return mCache; } - -bool LLExperienceCache::expirationFromCacheControl(LLSD headers, F64 *expires) +void LLExperienceCache::requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &httpAdapter, std::string url, RequestQueue_t requests) { - // Allow the header to override the default - LLSD cache_control_header = headers["cache-control"]; - if (cache_control_header.isDefined()) - { - S32 max_age = 0; - std::string cache_control = cache_control_header.asString(); - if (max_age_from_cache_control(cache_control, &max_age)) - { - LL_WARNS("ExperienceCache") - << "got EXPIRES from headers, max_age " << max_age - << LL_ENDL; - F64 now = LLFrameTimer::getTotalSeconds(); - *expires = now + (F64)max_age; - return true; - } - } - return false; -} + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest()); + //LL_INFOS("requestExperiencesCoro") << "url: " << url << LL_ENDL; -static const std::string MAX_AGE("max-age"); -static const boost::char_separator EQUALS_SEPARATOR("="); -static const boost::char_separator COMMA_SEPARATOR(","); + LLSD result = httpAdapter->getAndYield(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + if (!status) + { + F64 now = LLFrameTimer::getTotalSeconds(); -class LLExperienceResponder : public LLHTTPClient::Responder -{ -public: - LLExperienceResponder(const ask_queue_t& keys) - :mKeys(keys) - { - - } - - /*virtual*/ void httpCompleted() - { - LLSD experiences = getContent()["experience_keys"]; - LLSD::array_const_iterator it = experiences.beginArray(); - for( /**/ ; it != experiences.endArray(); ++it) - { - const LLSD& row = *it; - LLUUID public_key = row[EXPERIENCE_ID].asUUID(); - - - LL_DEBUGS("ExperienceCache") << "Received result for " << public_key - << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL ; - - processExperience(public_key, row); - } - - LLSD error_ids = getContent()["error_ids"]; - LLSD::array_const_iterator errIt = error_ids.beginArray(); - for( /**/ ; errIt != error_ids.endArray() ; ++errIt ) - { - LLUUID id = errIt->asUUID(); - LLSD exp; - exp[EXPIRES]=DEFAULT_EXPIRATION; - exp[EXPERIENCE_ID] = id; - exp[PROPERTIES]=PROPERTY_INVALID; - exp[MISSING]=true; - exp[QUOTA] = DEFAULT_QUOTA; - - processExperience(id, exp); - LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL ; - } - - LL_DEBUGS("ExperienceCache") << sCache.size() << " cached experiences" << LL_ENDL; - } - - /*virtual*/ void httpFailure() - { - LL_WARNS("ExperienceCache") << "Request failed "<first); + LLSD headers = httpResults[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_HEADERS]; + // build dummy entries for the failed requests + for (RequestQueue_t::const_iterator it = requests.begin(); it != requests.end(); ++it) + { + LLSD exp = get(*it); //leave the properties alone if we already have a cache entry for this xp - if(exp.isUndefined()) + if (exp.isUndefined()) { - exp[PROPERTIES]=PROPERTY_INVALID; + exp[PROPERTIES] = PROPERTY_INVALID; } - exp[EXPIRES]=retry_timestamp; - exp[EXPERIENCE_ID] = it->first; - exp["key_type"] = it->second; - exp["uuid"] = it->first; - exp["error"] = (LLSD::Integer)getStatus(); + exp[EXPIRES] = now + LLExperienceCacheImpl::getErrorRetryDeltaTime(status, headers); + exp[EXPERIENCE_ID] = *it; + exp["key_type"] = EXPERIENCE_ID; + exp["uuid"] = *it; + exp["error"] = (LLSD::Integer)status.getType(); exp[QUOTA] = DEFAULT_QUOTA; - LLExperienceCache::processExperience(it->first, exp); - } - - } - - // Return time to retry a request that generated an error, based on - // error type and headers. Return value is seconds-since-epoch. - F64 errorRetryTimestamp(S32 status) - { + processExperience(*it, exp); + } + return; + } - // Retry-After takes priority - LLSD retry_after = getResponseHeaders()["retry-after"]; - if (retry_after.isDefined()) - { - // We only support the delta-seconds type - S32 delta_seconds = retry_after.asInteger(); - if (delta_seconds > 0) - { - // ...valid delta-seconds - return F64(delta_seconds); - } - } + LLSD experiences = result["experience_keys"]; + + for (LLSD::array_const_iterator it = experiences.beginArray(); + it != experiences.endArray(); ++it) + { + const LLSD& row = *it; + LLUUID public_key = row[EXPERIENCE_ID].asUUID(); - // If no Retry-After, look for Cache-Control max-age - F64 expires = 0.0; - if (LLExperienceCache::expirationFromCacheControl(getResponseHeaders(), &expires)) - { - return expires; - } + LL_DEBUGS("ExperienceCache") << "Received result for " << public_key + << " display '" << row[LLExperienceCache::NAME].asString() << "'" << LL_ENDL; - // No information in header, make a guess - if (status == 503) - { - // ...service unavailable, retry soon - const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min - return SERVICE_UNAVAILABLE_DELAY; - } - else if (status == 499) - { - // ...we were probably too busy, retry quickly - const F64 BUSY_DELAY = 10.0; // 10 seconds - return BUSY_DELAY; + processExperience(public_key, row); + } - } - else - { - // ...other unexpected error - const F64 DEFAULT_DELAY = 3600.0; // 1 hour - return DEFAULT_DELAY; - } - } + LLSD error_ids = result["error_ids"]; + + for (LLSD::array_const_iterator errIt = error_ids.beginArray(); + errIt != error_ids.endArray(); ++errIt) + { + LLUUID id = errIt->asUUID(); + LLSD exp; + exp[EXPIRES] = DEFAULT_EXPIRATION; + exp[EXPERIENCE_ID] = id; + exp[PROPERTIES] = PROPERTY_INVALID; + exp[MISSING] = true; + exp[QUOTA] = DEFAULT_QUOTA; + + processExperience(id, exp); + LL_WARNS("ExperienceCache") << "LLExperienceResponder::result() error result for " << id << LL_ENDL; + } -private: - ask_queue_t mKeys; -}; +} void LLExperienceCache::requestExperiences() { - if(sAskQueue.empty() || sLookupURL.empty()) - return; - - F64 now = LLFrameTimer::getTotalSeconds(); + if (mCapability.empty()) + { + LL_WARNS("ExperienceCache") << "Capability query method not set." << LL_ENDL; + return; + } - const U32 EXP_URL_SEND_THRESHOLD = 3000; - const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD/UUID_STR_LENGTH; + std::string urlBase = mCapability("GetExperienceInfo"); + if (urlBase.empty()) + { + LL_WARNS("ExperienceCache") << "No Experience capability." << LL_ENDL; + return; + } - std::ostringstream ostr; + if (*urlBase.rbegin() != '/') + { + urlBase += "/"; + } + urlBase += "id/"; - ask_queue_t keys; - ostr << sLookupURL << "?page_size=" << PAGE_SIZE; + F64 now = LLFrameTimer::getTotalSeconds(); - int request_count = 0; - while(!sAskQueue.empty() && request_count < sMaximumLookups) - { - ask_queue_t::iterator it = sAskQueue.begin(); - const LLUUID& key = it->first; - const std::string& key_type = it->second; + const U32 EXP_URL_SEND_THRESHOLD = 3000; + const U32 PAGE_SIZE = EXP_URL_SEND_THRESHOLD / UUID_STR_LENGTH; - ostr << '&' << key_type << '=' << key.asString() ; - - keys[key]=key_type; - request_count++; + std::ostringstream ostr; + ostr << urlBase << "?page_size=" << PAGE_SIZE; + RequestQueue_t requests; - sPendingQueue[key] = now; - - if(ostr.tellp() > EXP_URL_SEND_THRESHOLD) - { - LL_DEBUGS("ExperienceCache") << "requestExperiences() query: " << ostr.str() << LL_ENDL; - LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); - ostr.clear(); - ostr.str(sLookupURL); - ostr << "?page_size=" << PAGE_SIZE; - keys.clear(); - } - sAskQueue.erase(it); - } + while (!mRequestQueue.empty()) + { + RequestQueue_t::iterator it = mRequestQueue.begin(); + LLUUID key = (*it); + mRequestQueue.erase(it); + requests.insert(key); + + ostr << "&" << EXPERIENCE_ID << "=" << key.asString(); + mPendingQueue[key] = now; + + if (mRequestQueue.empty() || (ostr.tellp() > EXP_URL_SEND_THRESHOLD)) + { // request is placed in the coprocedure pool for the ExpCache cache. Throttling is done by the pool itself. + LLCoprocedureManager::getInstance()->enqueueCoprocedure("ExpCache", "Request", + boost::bind(&LLExperienceCache::requestExperiencesCoro, this, _1, ostr.str(), requests) ); + + ostr.str(std::string()); + ostr << urlBase << "?page_size=" << PAGE_SIZE; + requests.clear(); + } + } - if(ostr.tellp() > sLookupURL.size()) - { - LL_DEBUGS("ExperienceCache") << "requestExperiences() query 2: " << ostr.str() << LL_ENDL; - LLHTTPClient::get(ostr.str(), new LLExperienceResponder(keys)); - } } @@ -427,9 +373,9 @@ bool LLExperienceCache::isRequestPending(const LLUUID& public_key) bool isPending = false; const F64 PENDING_TIMEOUT_SECS = 5.0 * 60.0; - pending_queue_t::const_iterator it = sPendingQueue.find(public_key); + PendingQueue_t::const_iterator it = mPendingQueue.find(public_key); - if(it != sPendingQueue.end()) + if(it != mPendingQueue.end()) { F64 expire_time = LLFrameTimer::getTotalSeconds() - PENDING_TIMEOUT_SECS; isPending = (it->second > expire_time); @@ -438,69 +384,70 @@ bool LLExperienceCache::isRequestPending(const LLUUID& public_key) return isPending; } - -void LLExperienceCache::setLookupURL(const std::string& lookup_url) +void LLExperienceCache::setCapabilityQuery(LLExperienceCache::CapabilityQuery_t queryfn) { - sLookupURL = lookup_url; - if(!sLookupURL.empty()) - { - sLookupURL += "id/"; - } + mCapability = queryfn; } -bool LLExperienceCache::hasLookupURL() -{ - return !sLookupURL.empty(); -} -void LLExperienceCache::idle() +void LLExperienceCache::idleCoro() { - const F32 SECS_BETWEEN_REQUESTS = 0.1f; - if (!sRequestTimer.checkExpirationAndReset(SECS_BETWEEN_REQUESTS)) - { - return; - } + const F32 SECS_BETWEEN_REQUESTS = 0.5f; + const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds - // Must be large relative to above - const F32 ERASE_EXPIRED_TIMEOUT = 60.f; // seconds - if (sEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) - { - eraseExpired(); - } + LL_INFOS("ExperienceCache") << "Launching Experience cache idle coro." << LL_ENDL; + LLEventTimeout timeout; - if(!sAskQueue.empty()) - { - requestExperiences(); - } + do + { + timeout.eventAfter(SECS_BETWEEN_REQUESTS, LLSD()); + llcoro::waitForEventOn(timeout); + + if (mEraseExpiredTimer.checkExpirationAndReset(ERASE_EXPIRED_TIMEOUT)) + { + eraseExpired(); + } + + if (!mRequestQueue.empty()) + { + requestExperiences(); + } + + } while (!mShutdown); + + // The coroutine system will likely be shut down by the time we get to this point + // (or at least no further cycling will occur on it since the user has decided to quit.) } void LLExperienceCache::erase(const LLUUID& key) { - cache_t::iterator it = sCache.find(key); + cache_t::iterator it = mCache.find(key); - if(it != sCache.end()) + if(it != mCache.end()) { - sCache.erase(it); + mCache.erase(it); } } void LLExperienceCache::eraseExpired() { F64 now = LLFrameTimer::getTotalSeconds(); - cache_t::iterator it = sCache.begin(); - while (it != sCache.end()) + cache_t::iterator it = mCache.begin(); + while (it != mCache.end()) { cache_t::iterator cur = it; LLSD& exp = cur->second; ++it; + //LL_INFOS("ExperienceCache") << "Testing experience \"" << exp[NAME] << "\" with exp time " << exp[EXPIRES].asReal() << "(now = " << now << ")" << LL_ENDL; + if(exp.has(EXPIRES) && exp[EXPIRES].asReal() < now) { if(!exp.has(EXPERIENCE_ID)) { LL_WARNS("ExperienceCache") << "Removing experience with no id " << LL_ENDL ; - sCache.erase(cur); - } + mCache.erase(cur); + } else { LLUUID id = exp[EXPERIENCE_ID].asUUID(); @@ -512,7 +459,7 @@ void LLExperienceCache::eraseExpired() else { LL_WARNS("ExperienceCache") << "Removing invalid experience " << id << LL_ENDL ; - sCache.erase(cur); + mCache.erase(cur); } } } @@ -521,11 +468,11 @@ void LLExperienceCache::eraseExpired() bool LLExperienceCache::fetch(const LLUUID& key, bool refresh/* = true*/) { - if(!key.isNull() && !isRequestPending(key) && (refresh || sCache.find(key)==sCache.end())) + if(!key.isNull() && !isRequestPending(key) && (refresh || mCache.find(key)==mCache.end())) { - LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL ; - sAskQueue[key]=EXPERIENCE_ID; + LL_DEBUGS("ExperienceCache") << " queue request for " << EXPERIENCE_ID << " " << key << LL_ENDL; + mRequestQueue.insert(key); return true; } return false; @@ -549,13 +496,12 @@ const LLSD& LLExperienceCache::get(const LLUUID& key) if(key.isNull()) return empty; - cache_t::const_iterator it = sCache.find(key); + cache_t::const_iterator it = mCache.find(key); - if (it != sCache.end()) + if (it != mCache.end()) { return it->second; } - fetch(key); return empty; @@ -565,8 +511,8 @@ void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::Callback_t slo if(key.isNull()) return; - cache_t::const_iterator it = sCache.find(key); - if (it != sCache.end()) + cache_t::const_iterator it = mCache.find(key); + if (it != mCache.end()) { // ...name already exists in cache, fire callback now callback_signal_t signal; @@ -580,28 +526,10 @@ void LLExperienceCache::get(const LLUUID& key, LLExperienceCache::Callback_t slo signal_ptr signal = signal_ptr(new callback_signal_t()); - std::pair result = sSignalMap.insert(signal_map_t::value_type(key, signal)); + std::pair result = mSignalMap.insert(signal_map_t::value_type(key, signal)); if (!result.second) - signal = result.first.second; + signal = (*result.first).second; signal->connect(slot); - -#if 0 - // always store additional callback, even if request is pending - signal_map_t::iterator sig_it = sSignalMap.find(key); - if (sig_it == sSignalMap.end()) - { - // ...new callback for this id - signal_ptr signal = signal_ptr(new callback_signal_t()); - signal->connect(slot); - sSignalMap[key] = signal; - } - else - { - // ...existing callback, bind additional slot - callback_signal_t* signal = sig_it->second; - signal->connect(slot); - } -#endif } //========================================================================= @@ -610,14 +538,71 @@ void LLExperienceCacheImpl::mapKeys(const LLSD& legacyKeys) LLSD::array_const_iterator exp = legacyKeys.beginArray(); for (/**/; exp != legacyKeys.endArray(); ++exp) { - if (exp->has(LLExperienceCache::EXPERIENCE_ID) && exp->has(LLExperienceCache::PRIVATE_KEY)) + if (exp->has(LLExperienceCacheImpl::EXPERIENCE_ID) && exp->has(LLExperienceCacheImpl::PRIVATE_KEY)) { - privateToPublicKeyMap[(*exp)[LLExperienceCache::PRIVATE_KEY].asUUID()] = (*exp)[LLExperienceCache::EXPERIENCE_ID].asUUID(); + LLExperienceCacheImpl::privateToPublicKeyMap[(*exp)[LLExperienceCacheImpl::PRIVATE_KEY].asUUID()] = + (*exp)[LLExperienceCacheImpl::EXPERIENCE_ID].asUUID(); } } } -bool LLExperienceCacheImpl::max_age_from_cache_control(const std::string& cache_control, S32 *max_age) +// Return time to retry a request that generated an error, based on +// error type and headers. Return value is seconds-since-epoch. +F64 LLExperienceCacheImpl::getErrorRetryDeltaTime(S32 status, LLSD headers) +{ + + // Retry-After takes priority + LLSD retry_after = headers["retry-after"]; + if (retry_after.isDefined()) + { + // We only support the delta-seconds type + S32 delta_seconds = retry_after.asInteger(); + if (delta_seconds > 0) + { + // ...valid delta-seconds + return F64(delta_seconds); + } + } + + // If no Retry-After, look for Cache-Control max-age + // Allow the header to override the default + LLSD cache_control_header = headers["cache-control"]; + if (cache_control_header.isDefined()) + { + S32 max_age = 0; + std::string cache_control = cache_control_header.asString(); + if (LLExperienceCacheImpl::maxAgeFromCacheControl(cache_control, &max_age)) + { + LL_WARNS("ExperienceCache") + << "got EXPIRES from headers, max_age " << max_age + << LL_ENDL; + return (F64)max_age; + } + } + + // No information in header, make a guess + if (status == 503) + { + // ...service unavailable, retry soon + const F64 SERVICE_UNAVAILABLE_DELAY = 600.0; // 10 min + return SERVICE_UNAVAILABLE_DELAY; + } + else if (status == 499) + { + // ...we were probably too busy, retry quickly + const F64 BUSY_DELAY = 10.0; // 10 seconds + return BUSY_DELAY; + + } + else + { + // ...other unexpected error + const F64 DEFAULT_DELAY = 3600.0; // 1 hour + return DEFAULT_DELAY; + } +} + +bool LLExperienceCacheImpl::maxAgeFromCacheControl(const std::string& cache_control, S32 *max_age) { // Split the string on "," to get a list of directives typedef boost::tokenizer > tokenizer; diff --git a/indra/llmessage/llexperiencecache.h b/indra/llmessage/llexperiencecache.h index 8da038a8c3..937225a80a 100644 --- a/indra/llmessage/llexperiencecache.h +++ b/indra/llmessage/llexperiencecache.h @@ -31,7 +31,9 @@ #include "linden_common.h" #include "llsingleton.h" +#include "llframetimer.h" #include "llsd.h" +#include "llcorehttputil.h" #include #include @@ -44,8 +46,11 @@ class LLExperienceCache: public LLSingleton < LLExperienceCache > friend class LLSingleton < LLExperienceCache > ; public: + typedef boost::function CapabilityQuery_t; typedef boost::function Callback_t; + void cleanup(); + void erase(const LLUUID& key); bool fetch(const LLUUID& key, bool refresh = false); void insert(const LLSD& experience_data); @@ -54,7 +59,39 @@ public: // If name information is in cache, callback will be called immediately. void get(const LLUUID& key, Callback_t slot); + bool isRequestPending(const LLUUID& public_key); + + void setCapabilityQuery(CapabilityQuery_t queryfn); + + static const std::string NAME; // "name" + static const std::string EXPERIENCE_ID; // "public_id" + static const std::string AGENT_ID; // "agent_id" + static const std::string GROUP_ID; // "group_id" + static const std::string PROPERTIES; // "properties" + static const std::string EXPIRES; // "expiration" + static const std::string DESCRIPTION; // "description" + static const std::string QUOTA; // "quota" + static const std::string MATURITY; // "maturity" + static const std::string METADATA; // "extended_metadata" + static const std::string SLURL; // "slurl" + + static const std::string MISSING; // "DoesNotExist" + + // should be in sync with experience-api/experiences/models.py + static const int PROPERTY_INVALID; // 1 << 0 + static const int PROPERTY_PRIVILEGED; // 1 << 3 + static const int PROPERTY_GRID; // 1 << 4 + static const int PROPERTY_PRIVATE; // 1 << 5 + static const int PROPERTY_DISABLED; // 1 << 6 + static const int PROPERTY_SUSPENDED; // 1 << 7 + private: + LLExperienceCache(); + virtual ~LLExperienceCache(); + + virtual void initSingleton(); + + // Callback types for get() typedef boost::signals2::signal < void(const LLSD &) > callback_signal_t; typedef boost::shared_ptr signal_ptr; @@ -64,63 +101,43 @@ private: typedef std::map signal_map_t; typedef std::map cache_t; - typedef std::set ask_queue_t; - - + typedef std::set RequestQueue_t; + typedef std::map PendingQueue_t; + //-------------------------------------------- static const std::string PRIVATE_KEY; // "private_id" - static const std::string MISSING; // "DoesNotExist" - - static const std::string AGENT_ID; // "agent_id" - static const std::string GROUP_ID; // "group_id" - static const std::string EXPERIENCE_ID; // "public_id" - static const std::string NAME; // "name" - static const std::string PROPERTIES; // "properties" - static const std::string EXPIRES; // "expiration" - static const std::string DESCRIPTION; // "description" - static const std::string QUOTA; // "quota" - static const std::string MATURITY; // "maturity" - static const std::string METADATA; // "extended_metadata" - static const std::string SLURL; // "slurl" - - // should be in sync with experience-api/experiences/models.py - static const int PROPERTY_INVALID; // 1 << 0 - static const int PROPERTY_PRIVILEGED; // 1 << 3 - static const int PROPERTY_GRID; // 1 << 4 - static const int PROPERTY_PRIVATE; // 1 << 5 - static const int PROPERTY_DISABLED; // 1 << 6 - static const int PROPERTY_SUSPENDED; // 1 << 7 // default values static const F64 DEFAULT_EXPIRATION; // 600.0 static const S32 DEFAULT_QUOTA; // 128 this is megabytes -//-------------------------------------------- - LLExperienceCache(); - virtual ~LLExperienceCache(); - - void exportFile(std::ostream& ostr) const; - void importFile(std::istream& istr); - //-------------------------------------------- void processExperience(const LLUUID& public_key, const LLSD& experience); //-------------------------------------------- - cache_t sCache; - signal_map_t sSignalMap; - ask_queue_t sAskQueue; - + cache_t mCache; + signal_map_t mSignalMap; + RequestQueue_t mRequestQueue; + PendingQueue_t mPendingQueue; + + LLFrameTimer mRequestTimer; + LLFrameTimer mEraseExpiredTimer; // Periodically clean out expired entries from the cache + CapabilityQuery_t mCapability; + std::string mCacheFileName; + bool mShutdown; + + void idleCoro(); void eraseExpired(); - - void setLookupURL(const std::string& lookup_url); - bool hasLookupURL(); + void requestExperiencesCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t &, std::string, RequestQueue_t); + void requestExperiences(); void setMaximumLookups(int maximumLookups); - void idle(); - void bootstrap(const LLSD& legacyKeys, int initialExpiration); - + void bootstrap(const LLSD& legacyKeys, int initialExpiration); + void exportFile(std::ostream& ostr) const; + void importFile(std::istream& istr); + // const cache_t& getCached(); // maps an experience private key to the experience id diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 259fbde806..d192aac448 100755 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -11,11 +11,13 @@ include(LLMessage) include(LLCoreHttp) include(LLRender) include(LLWindow) +include(LLCoreHttp) include(LLVFS) include(LLXML) include_directories( ${LLCOMMON_INCLUDE_DIRS} + ${LLCOREHTTP_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS} ${LLINVENTORY_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index eb7f98e618..e76f2a1550 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1430,7 +1430,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const return LLTrans::getString("ExperienceNameNull"); } - const LLSD& experience_details = LLExperienceCache::get(experience_id); + const LLSD& experience_details = LLExperienceCache::getInstance()->get(experience_id); if(!experience_details.isUndefined()) { std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString(); @@ -1438,7 +1438,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const } addObserver(experience_id_string, url, cb); - LLExperienceCache::get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); + LLExperienceCache::getInstance()->get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); return LLTrans::getString("LoadingData"); } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index fe9c7c0fc0..090879e372 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -161,7 +161,6 @@ set(viewer_SOURCE_FILES llconversationloglistitem.cpp llconversationmodel.cpp llconversationview.cpp - llcoproceduremanager.cpp llcurrencyuimanager.cpp llcylinder.cpp lldateutil.cpp @@ -771,7 +770,6 @@ set(viewer_HEADER_FILES llconversationloglistitem.h llconversationmodel.h llconversationview.h - llcoproceduremanager.h llcurrencyuimanager.h llcylinder.h lldateutil.h diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index e7dd378edd..3316f1e654 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -953,6 +953,15 @@ BOOL LLAgent::inPrelude() } +std::string LLAgent::getRegionCapability(const std::string &name) +{ + if (!mRegionp) + return std::string(); + + return mRegionp->getCapability(name); +} + + //----------------------------------------------------------------------------- // canManageEstate() //----------------------------------------------------------------------------- diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index 0ba3dea427..5731f4db89 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -262,6 +262,9 @@ public: LLHost getRegionHost() const; BOOL inPrelude(); + // Capability + std::string getRegionCapability(const std::string &name); // short hand for if (getRegion()) { getRegion()->getCapability(name) } + /** * Register a boost callback to be called when the agent changes regions * Note that if you need to access a capability for the region, you may need to wait diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 9b9b591cd1..e13a9d96c7 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -228,7 +228,7 @@ #include "llmachineid.h" #include "llmainlooprepeater.h" - +#include "llcoproceduremanager.h" #include "llviewereventrecorder.h" @@ -755,8 +755,11 @@ void fast_exit(int rc) { _exit(rc); } + + } + bool LLAppViewer::init() { setupErrorHandling(mSecondInstance); @@ -1216,6 +1219,12 @@ bool LLAppViewer::init() LLAgentLanguage::init(); + /// Tell the Coprocedure manager how to discover and store the pool sizes + // what I wanted + LLCoprocedureManager::getInstance()->setPropertyMethods( + boost::bind(&LLControlGroup::getU32, boost::ref(gSavedSettings), _1), + boost::bind(&LLControlGroup::declareU32, boost::ref(gSavedSettings), _1, _2, _3, LLControlVariable::PERSIST_ALWAYS)); + return true; } @@ -4700,31 +4709,6 @@ void LLAppViewer::saveNameCache() } -void LLAppViewer::saveExperienceCache() -{ - std::string filename = - gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); - LL_INFOS("ExperienceCache") << "Saving " << filename << LL_ENDL; - llofstream cache_stream(filename.c_str()); - if(cache_stream.is_open()) - { - LLExperienceCache::exportFile(cache_stream); - } -} - -void LLAppViewer::loadExperienceCache() -{ - std::string filename = - gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "experience_cache.xml"); - LL_INFOS("ExperienceCache") << "Loading " << filename << LL_ENDL; - llifstream cache_stream(filename.c_str()); - if(cache_stream.is_open()) - { - LLExperienceCache::importFile(cache_stream); - } -} - - /*! @brief This class is an LLFrameTimer that can be created with an elapsed time that starts counting up from the given value rather than 0.0. @@ -4920,7 +4904,6 @@ void LLAppViewer::idle() // floating throughout the various object lists. // idleNameCache(); - idleExperienceCache(); idleNetwork(); @@ -5350,22 +5333,6 @@ void LLAppViewer::idleNameCache() LLAvatarNameCache::idle(); } -void LLAppViewer::idleExperienceCache() -{ - LLViewerRegion* region = gAgent.getRegion(); - if (!region) return; - - std::string lookup_url=region->getCapability("GetExperienceInfo"); - if(!lookup_url.empty() && *lookup_url.rbegin() != '/') - { - lookup_url += '/'; - } - - LLExperienceCache::setLookupURL(lookup_url); - - LLExperienceCache::idle(); -} - // // Handle messages, and all message related stuff // @@ -5528,7 +5495,9 @@ void LLAppViewer::disconnectViewer() } saveNameCache(); - saveExperienceCache(); + LLExperienceCache *expCache = LLExperienceCache::getIfExists(); + if (expCache) + expCache->cleanup(); // close inventory interface, close all windows LLFloaterInventory::cleanup(); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 718871138e..e8a1ca036b 100755 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -122,9 +122,6 @@ public: void loadNameCache(); void saveNameCache(); - void loadExperienceCache(); - void saveExperienceCache(); - void removeMarkerFiles(); void removeDumpDir(); @@ -233,7 +230,6 @@ private: void idle(); void idleShutdown(); // update avatar SLID and display name caches - void idleExperienceCache(); void idleNameCache(); void idleNetwork(); diff --git a/indra/newview/llcoproceduremanager.cpp b/indra/newview/llcoproceduremanager.cpp deleted file mode 100644 index db01c13079..0000000000 --- a/indra/newview/llcoproceduremanager.cpp +++ /dev/null @@ -1,406 +0,0 @@ -/** -* @file LLCoprocedurePool.cpp -* @author Rider Linden -* @brief Singleton class for managing asset uploads to the sim. -* -* $LicenseInfo:firstyear=2015&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2015, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#include "llviewerprecompiledheaders.h" -#include "linden_common.h" - -#include "llviewercontrol.h" - -#include "llcoproceduremanager.h" - -//========================================================================= -// Map of pool sizes for known pools -static std::map DefaultPoolSizes; - -// *TODO$: When C++11 this can be initialized here as follows: -// = {{"AIS", 25}, {"Upload", 1}} - -#define DEFAULT_POOL_SIZE 5 - -//========================================================================= -class LLCoprocedurePool: private boost::noncopyable -{ -public: - typedef LLCoprocedureManager::CoProcedure_t CoProcedure_t; - - LLCoprocedurePool(const std::string &name, size_t size); - virtual ~LLCoprocedurePool(); - - /// Places the coprocedure on the queue for processing. - /// - /// @param name Is used for debugging and should identify this coroutine. - /// @param proc Is a bound function to be executed - /// - /// @return This method returns a UUID that can be used later to cancel execution. - LLUUID enqueueCoprocedure(const std::string &name, CoProcedure_t proc); - - /// Cancel a coprocedure. If the coprocedure is already being actively executed - /// this method calls cancelYieldingOperation() on the associated HttpAdapter - /// If it has not yet been dequeued it is simply removed from the queue. - bool cancelCoprocedure(const LLUUID &id); - - /// Requests a shutdown of the upload manager. Passing 'true' will perform - /// an immediate kill on the upload coroutine. - void shutdown(bool hardShutdown = false); - - /// Returns the number of coprocedures in the queue awaiting processing. - /// - inline size_t countPending() const - { - return mPendingCoprocs.size(); - } - - /// Returns the number of coprocedures actively being processed. - /// - inline size_t countActive() const - { - return mActiveCoprocs.size(); - } - - /// Returns the total number of coprocedures either queued or in active processing. - /// - inline size_t count() const - { - return countPending() + countActive(); - } - -private: - struct QueuedCoproc - { - typedef boost::shared_ptr ptr_t; - - QueuedCoproc(const std::string &name, const LLUUID &id, CoProcedure_t proc) : - mName(name), - mId(id), - mProc(proc) - {} - - std::string mName; - LLUUID mId; - CoProcedure_t mProc; - }; - - // we use a deque here rather than std::queue since we want to be able to - // iterate through the queue and potentially erase an entry from the middle. - typedef std::deque CoprocQueue_t; - typedef std::map ActiveCoproc_t; - - std::string mPoolName; - size_t mPoolSize; - CoprocQueue_t mPendingCoprocs; - ActiveCoproc_t mActiveCoprocs; - bool mShutdown; - LLEventStream mWakeupTrigger; - - typedef std::map CoroAdapterMap_t; - LLCore::HttpRequest::policy_t mHTTPPolicy; - - CoroAdapterMap_t mCoroMapping; - - void coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter); - -}; - -//========================================================================= -LLCoprocedureManager::LLCoprocedureManager() -{ - DefaultPoolSizes.insert(std::map::value_type("Upload", 1)); - DefaultPoolSizes.insert(std::map::value_type("AIS", 25)); -} - -LLCoprocedureManager::~LLCoprocedureManager() -{ - -} - -LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std::string &poolName) -{ - // Attempt to look up a pool size in the configuration. If found use that - std::string keyName = "PoolSize" + poolName; - int size = 5; - - size = gSavedSettings.getU32(keyName); - if (size == 0) - { // if not found grab the know default... if there is no known - // default use a reasonable number like 5. - std::map::iterator it = DefaultPoolSizes.find(poolName); - if (it == DefaultPoolSizes.end()) - size = DEFAULT_POOL_SIZE; - else - size = (*it).second; - gSavedSettings.declareU32(keyName, size, "Coroutine Pool size for " + poolName, LLControlVariable::PERSIST_ALWAYS); - LL_WARNS() << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL; - } - - poolPtr_t pool = poolPtr_t(new LLCoprocedurePool(poolName, size)); - mPoolMap.insert(poolMap_t::value_type(poolName, pool)); - - return pool; -} - -//------------------------------------------------------------------------- -LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc) -{ - // Attempt to find the pool and enqueue the procedure. If the pool does - // not exist, create it. - poolPtr_t targetPool; - poolMap_t::iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - { - targetPool = initializePool(pool); - } - else - { - targetPool = (*it).second; - } - - if (!targetPool) - { - LL_WARNS() << "LLCoprocedureManager unable to create coprocedure pool named \"" << pool << "\"" << LL_ENDL; - return LLUUID::null; - } - - return targetPool->enqueueCoprocedure(name, proc); -} - -void LLCoprocedureManager::cancelCoprocedure(const LLUUID &id) -{ - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - if ((*it).second->cancelCoprocedure(id)) - return; - } - LL_INFOS() << "Coprocedure not found." << LL_ENDL; -} - -void LLCoprocedureManager::shutdown(bool hardShutdown) -{ - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - (*it).second->shutdown(hardShutdown); - } - mPoolMap.clear(); -} - -//------------------------------------------------------------------------- -size_t LLCoprocedureManager::countPending() const -{ - size_t count = 0; - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - count += (*it).second->countPending(); - } - return count; -} - -size_t LLCoprocedureManager::countPending(const std::string &pool) const -{ - poolMap_t::const_iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - return 0; - return (*it).second->countPending(); -} - -size_t LLCoprocedureManager::countActive() const -{ - size_t count = 0; - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - count += (*it).second->countActive(); - } - return count; -} - -size_t LLCoprocedureManager::countActive(const std::string &pool) const -{ - poolMap_t::const_iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - return 0; - return (*it).second->countActive(); -} - -size_t LLCoprocedureManager::count() const -{ - size_t count = 0; - for (poolMap_t::const_iterator it = mPoolMap.begin(); it != mPoolMap.end(); ++it) - { - count += (*it).second->count(); - } - return count; -} - -size_t LLCoprocedureManager::count(const std::string &pool) const -{ - poolMap_t::const_iterator it = mPoolMap.find(pool); - - if (it == mPoolMap.end()) - return 0; - return (*it).second->count(); -} - -//========================================================================= -LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size): - mPoolName(poolName), - mPoolSize(size), - mPendingCoprocs(), - mShutdown(false), - mWakeupTrigger("CoprocedurePool" + poolName, true), - mCoroMapping(), - mHTTPPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID) -{ - for (size_t count = 0; count < mPoolSize; ++count) - { - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter = - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t( - new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy)); - - std::string uploadCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro", - boost::bind(&LLCoprocedurePool::coprocedureInvokerCoro, this, httpAdapter)); - - mCoroMapping.insert(CoroAdapterMap_t::value_type(uploadCoro, httpAdapter)); - } - - LL_INFOS() << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items." << LL_ENDL; - - mWakeupTrigger.post(LLSD()); -} - -LLCoprocedurePool::~LLCoprocedurePool() -{ - shutdown(); -} - -//------------------------------------------------------------------------- -void LLCoprocedurePool::shutdown(bool hardShutdown) -{ - CoroAdapterMap_t::iterator it; - - for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it) - { - if (!(*it).first.empty()) - { - if (hardShutdown) - { - LLCoros::instance().kill((*it).first); - } - } - if ((*it).second) - { - (*it).second->cancelYieldingOperation(); - } - } - - mShutdown = true; - mCoroMapping.clear(); - mPendingCoprocs.clear(); -} - -//------------------------------------------------------------------------- -LLUUID LLCoprocedurePool::enqueueCoprocedure(const std::string &name, LLCoprocedurePool::CoProcedure_t proc) -{ - LLUUID id(LLUUID::generateNewID()); - - mPendingCoprocs.push_back(QueuedCoproc::ptr_t(new QueuedCoproc(name, id, proc))); - LL_INFOS() << "Coprocedure(" << name << ") enqueued with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - - mWakeupTrigger.post(LLSD()); - - return id; -} - -bool LLCoprocedurePool::cancelCoprocedure(const LLUUID &id) -{ - // first check the active coroutines. If there, remove it and return. - ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(id); - if (itActive != mActiveCoprocs.end()) - { - LL_INFOS() << "Found and canceling active coprocedure with id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - (*itActive).second->cancelYieldingOperation(); - mActiveCoprocs.erase(itActive); - return true; - } - - for (CoprocQueue_t::iterator it = mPendingCoprocs.begin(); it != mPendingCoprocs.end(); ++it) - { - if ((*it)->mId == id) - { - LL_INFOS() << "Found and removing queued coroutine(" << (*it)->mName << ") with Id=" << id.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - mPendingCoprocs.erase(it); - return true; - } - } - - LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found." << " in pool \"" << mPoolName << "\"" << LL_ENDL; - return false; -} - -//------------------------------------------------------------------------- -void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter) -{ - LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); - - while (!mShutdown) - { - llcoro::waitForEventOn(mWakeupTrigger); - if (mShutdown) - break; - - while (!mPendingCoprocs.empty()) - { - QueuedCoproc::ptr_t coproc = mPendingCoprocs.front(); - mPendingCoprocs.pop_front(); - mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)); - - LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; - - try - { - coproc->mProc(httpAdapter, coproc->mId); - } - catch (std::exception &e) - { - LL_WARNS() << "Coprocedure(" << coproc->mName << ") id=" << coproc->mId.asString() << - " threw an exception! Message=\"" << e.what() << "\"" << LL_ENDL; - } - catch (...) - { - LL_WARNS() << "A non std::exception was thrown from " << coproc->mName << " with id=" << coproc->mId << "." << " in pool \"" << mPoolName << "\"" << LL_ENDL; - } - - LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL; - - ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(coproc->mId); - if (itActive != mActiveCoprocs.end()) - { - mActiveCoprocs.erase(itActive); - } - } - } -} diff --git a/indra/newview/llcoproceduremanager.h b/indra/newview/llcoproceduremanager.h deleted file mode 100644 index d7f74af76b..0000000000 --- a/indra/newview/llcoproceduremanager.h +++ /dev/null @@ -1,87 +0,0 @@ -/** -* @file llcoproceduremanager.h -* @author Rider Linden -* @brief Singleton class for managing asset uploads to the sim. -* -* $LicenseInfo:firstyear=2015&license=viewerlgpl$ -* Second Life Viewer Source Code -* Copyright (C) 2015, Linden Research, Inc. -* -* This library is free software; you can redistribute it and/or -* modify it under the terms of the GNU Lesser General Public -* License as published by the Free Software Foundation; -* version 2.1 of the License only. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -* -* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA -* $/LicenseInfo$ -*/ - -#ifndef LL_COPROCEDURE_MANAGER_H -#define LL_COPROCEDURE_MANAGER_H - -#include "lleventcoro.h" -#include "llcoros.h" -#include "llcorehttputil.h" -#include "lluuid.h" - -class LLCoprocedurePool; - -class LLCoprocedureManager : public LLSingleton < LLCoprocedureManager > -{ -public: - typedef boost::function CoProcedure_t; - - LLCoprocedureManager(); - virtual ~LLCoprocedureManager(); - - /// Places the coprocedure on the queue for processing. - /// - /// @param name Is used for debugging and should identify this coroutine. - /// @param proc Is a bound function to be executed - /// - /// @return This method returns a UUID that can be used later to cancel execution. - LLUUID enqueueCoprocedure(const std::string &pool, const std::string &name, CoProcedure_t proc); - - /// Cancel a coprocedure. If the coprocedure is already being actively executed - /// this method calls cancelYieldingOperation() on the associated HttpAdapter - /// If it has not yet been dequeued it is simply removed from the queue. - void cancelCoprocedure(const LLUUID &id); - - /// Requests a shutdown of the upload manager. Passing 'true' will perform - /// an immediate kill on the upload coroutine. - void shutdown(bool hardShutdown = false); - - /// Returns the number of coprocedures in the queue awaiting processing. - /// - size_t countPending() const; - size_t countPending(const std::string &pool) const; - - /// Returns the number of coprocedures actively being processed. - /// - size_t countActive() const; - size_t countActive(const std::string &pool) const; - - /// Returns the total number of coprocedures either queued or in active processing. - /// - size_t count() const; - size_t count(const std::string &pool) const; - -private: - typedef boost::shared_ptr poolPtr_t; - typedef std::map poolMap_t; - - poolMap_t mPoolMap; - - poolPtr_t initializePool(const std::string &poolName); -}; - -#endif diff --git a/indra/newview/llexperienceassociationresponder.cpp b/indra/newview/llexperienceassociationresponder.cpp index b50c81eedc..cd4a7516b1 100644 --- a/indra/newview/llexperienceassociationresponder.cpp +++ b/indra/newview/llexperienceassociationresponder.cpp @@ -83,7 +83,7 @@ void ExperienceAssociationResponder::httpSuccess() return; } - LLExperienceCache::get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1)); + LLExperienceCache::getInstance()->get(getContent()["experience"].asUUID(), boost::bind(&ExperienceAssociationResponder::sendResult, this, _1)); } diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp index 197162487d..8a04f9e4cc 100644 --- a/indra/newview/llfloaterexperienceprofile.cpp +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -99,7 +99,7 @@ public: if(params.size() != 2 || params[1].asString() != "profile") return false; - LLExperienceCache::get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); + LLExperienceCache::getInstance()->get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); return true; } @@ -288,8 +288,8 @@ BOOL LLFloaterExperienceProfile::postBuild() if (mExperienceId.notNull()) { - LLExperienceCache::fetch(mExperienceId, true); - LLExperienceCache::get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, + LLExperienceCache::getInstance()->fetch(mExperienceId, true); + LLExperienceCache::getInstance()->get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, getDerivedHandle(), _1)); LLViewerRegion* region = gAgent.getRegion(); @@ -799,8 +799,8 @@ void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content ) } refreshExperience(*it); - LLExperienceCache::insert(*it); - LLExperienceCache::fetch(id, true); + LLExperienceCache::getInstance()->insert(*it); + LLExperienceCache::getInstance()->fetch(id, true); if(mSaveCompleteAction==VIEW) { diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 370d0f4f1b..714d8d0e8f 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -268,7 +268,7 @@ void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id) if (LLUUID::null != mExperienceID) { - const LLSD& experience = LLExperienceCache::get(mExperienceID); + const LLSD& experience = LLExperienceCache::getInstance()->get(mExperienceID); std::stringstream desc; if(experience.isDefined()) diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp index fc4ee9862e..20fe0c52fa 100644 --- a/indra/newview/llpanelexperiencelisteditor.cpp +++ b/indra/newview/llpanelexperiencelisteditor.cpp @@ -183,7 +183,7 @@ void LLPanelExperienceListEditor::onItems() columns[0]["value"] = getString("loading"); mItems->addElement(item); - LLExperienceCache::get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, + LLExperienceCache::getInstance()->get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, getDerivedHandle(), _1)); } diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp index df03ef7526..9329d900b1 100644 --- a/indra/newview/llpanelexperiencelog.cpp +++ b/indra/newview/llpanelexperiencelog.cpp @@ -140,7 +140,7 @@ void LLPanelExperienceLog::refresh() } const LLSD event = dayArray[i]; LLUUID id = event[LLExperienceCache::EXPERIENCE_ID].asUUID(); - const LLSD& experience = LLExperienceCache::get(id); + const LLSD& experience = LLExperienceCache::getInstance()->get(id); if(experience.isUndefined()){ waiting = true; waiting_id = id; @@ -168,7 +168,7 @@ void LLPanelExperienceLog::refresh() { mEventList->deleteAllItems(); mEventList->setCommentText(getString("loading")); - LLExperienceCache::get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); + LLExperienceCache::getInstance()->get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); } else { diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp index c7a353a6af..7c19e32e7e 100644 --- a/indra/newview/llpanelexperiencepicker.cpp +++ b/indra/newview/llpanelexperiencepicker.cpp @@ -238,7 +238,7 @@ void LLPanelExperiencePicker::processResponse( const LLUUID& query_id, const LLS LLSD::array_const_iterator it = experiences.beginArray(); for ( ; it != experiences.endArray(); ++it) { - LLExperienceCache::insert(*it); + LLExperienceCache::getInstance()->insert(*it); } getChildView(BTN_RIGHT)->setEnabled(content.has("next_page_url")); diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index a548d7b705..4f5d21b6be 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1326,7 +1326,7 @@ void LLLiveLSLEditor::buildExperienceList() position = ADD_TOP; } - const LLSD& experience = LLExperienceCache::get(id); + const LLSD& experience = LLExperienceCache::getInstance()->get(id); if(experience.isUndefined()) { mExperiences->add(getString("loading"), id, position); @@ -1345,7 +1345,7 @@ void LLLiveLSLEditor::buildExperienceList() if(!foundAssociated ) { - const LLSD& experience = LLExperienceCache::get(associated); + const LLSD& experience = LLExperienceCache::getInstance()->get(associated); if(experience.isDefined()) { std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); @@ -1366,7 +1366,7 @@ void LLLiveLSLEditor::buildExperienceList() if(last.notNull()) { mExperiences->setEnabled(FALSE); - LLExperienceCache::get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); + LLExperienceCache::getInstance()->get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); } else { diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 46f75c4f57..361cc6c48b 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2821,9 +2821,10 @@ void LLStartUp::initNameCache() void LLStartUp::initExperiences() { - // just a get instance here. Should trigger loading the cache. - LLExperienceCache::getInstance(); - LLAppViewer::instance()->loadExperienceCache(); + // Should trigger loading the cache. + LLExperienceCache::getInstance()->setCapabilityQuery( + boost::bind(&LLAgent::getRegionCapability, &gAgent, _1)); + LLExperienceLog::instance().initialize(); } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 886725be79..4e1a86bb71 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6653,7 +6653,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data) else if(experienceid.notNull()) { payload["experience"]=experienceid; - LLExperienceCache::get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); + LLExperienceCache::getInstance()->get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); return; } -- cgit v1.3 From 8913ed6692fddc5d72ee01ecb92a21093c5d22ad Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Thu, 3 Sep 2015 16:59:00 -0700 Subject: Changes from code review with Nat --- indra/llmessage/llcoproceduremanager.cpp | 36 +++++++++------------------ indra/llui/llurlentry.cpp | 4 +-- indra/newview/llcompilequeue.cpp | 2 +- indra/newview/llfloaterexperienceprofile.cpp | 10 ++++---- indra/newview/llfloaterregioninfo.cpp | 4 +-- indra/newview/llfloaterreporter.cpp | 2 +- indra/newview/llpanelexperiencelisteditor.cpp | 2 +- indra/newview/llpanelexperiencelog.cpp | 4 +-- indra/newview/llpanelexperiencepicker.cpp | 2 +- indra/newview/llpanelgroupexperiences.cpp | 2 +- indra/newview/llpreviewscript.cpp | 8 +++--- indra/newview/llsidepaneliteminfo.cpp | 2 +- indra/newview/llstartup.cpp | 2 +- indra/newview/llviewermessage.cpp | 2 +- 14 files changed, 35 insertions(+), 47 deletions(-) (limited to 'indra/newview/llfloaterreporter.cpp') diff --git a/indra/llmessage/llcoproceduremanager.cpp b/indra/llmessage/llcoproceduremanager.cpp index c9dfcae293..68da248ee4 100644 --- a/indra/llmessage/llcoproceduremanager.cpp +++ b/indra/llmessage/llcoproceduremanager.cpp @@ -140,6 +140,8 @@ LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std:: std::string keyName = "PoolSize" + poolName; int size = 0; + LL_ERRS_IF(poolName.empty(), "CoprocedureManager") << "Poolname must not be empty" << LL_ENDL; + if (mPropertyQueryFn && !mPropertyQueryFn.empty()) { size = mPropertyQueryFn(keyName); @@ -159,9 +161,10 @@ LLCoprocedureManager::poolPtr_t LLCoprocedureManager::initializePool(const std:: LL_WARNS() << "LLCoprocedureManager: No setting for \"" << keyName << "\" setting pool size to default of " << size << LL_ENDL; } - poolPtr_t pool = poolPtr_t(new LLCoprocedurePool(poolName, size)); + poolPtr_t pool(new LLCoprocedurePool(poolName, size)); mPoolMap.insert(poolMap_t::value_type(poolName, pool)); + LL_ERRS_IF(!pool, "CoprocedureManager") << "Unable to create pool named \"" << poolName << "\" FATAL!" << LL_ENDL; return pool; } @@ -182,12 +185,6 @@ LLUUID LLCoprocedureManager::enqueueCoprocedure(const std::string &pool, const s targetPool = (*it).second; } - if (!targetPool) - { - LL_WARNS() << "LLCoprocedureManager unable to create coprocedure pool named \"" << pool << "\"" << LL_ENDL; - return LLUUID::null; - } - return targetPool->enqueueCoprocedure(name, proc); } @@ -286,14 +283,12 @@ LLCoprocedurePool::LLCoprocedurePool(const std::string &poolName, size_t size): { for (size_t count = 0; count < mPoolSize; ++count) { - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter = - LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t( - new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy)); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter( mPoolName + "Adapter", mHTTPPolicy)); - std::string uploadCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro", + std::string pooledCoro = LLCoros::instance().launch("LLCoprocedurePool("+mPoolName+")::coprocedureInvokerCoro", boost::bind(&LLCoprocedurePool::coprocedureInvokerCoro, this, httpAdapter)); - mCoroMapping.insert(CoroAdapterMap_t::value_type(uploadCoro, httpAdapter)); + mCoroMapping.insert(CoroAdapterMap_t::value_type(pooledCoro, httpAdapter)); } LL_INFOS() << "Created coprocedure pool named \"" << mPoolName << "\" with " << size << " items." << LL_ENDL; @@ -313,12 +308,9 @@ void LLCoprocedurePool::shutdown(bool hardShutdown) for (it = mCoroMapping.begin(); it != mCoroMapping.end(); ++it) { - if (!(*it).first.empty()) + if (hardShutdown) { - if (hardShutdown) - { - LLCoros::instance().kill((*it).first); - } + LLCoros::instance().kill((*it).first); } if ((*it).second) { @@ -366,7 +358,7 @@ bool LLCoprocedurePool::cancelCoprocedure(const LLUUID &id) } } - LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found." << " in pool \"" << mPoolName << "\"" << LL_ENDL; + LL_INFOS() << "Coprocedure with Id=" << id.asString() << " was not found in pool \"" << mPoolName << "\"" << LL_ENDL; return false; } @@ -385,7 +377,7 @@ void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdap { QueuedCoproc::ptr_t coproc = mPendingCoprocs.front(); mPendingCoprocs.pop_front(); - mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)); + ActiveCoproc_t::iterator itActive = mActiveCoprocs.insert(ActiveCoproc_t::value_type(coproc->mId, httpAdapter)).first; LL_INFOS() << "Dequeued and invoking coprocedure(" << coproc->mName << ") with id=" << coproc->mId.asString() << " in pool \"" << mPoolName << "\"" << LL_ENDL; @@ -405,11 +397,7 @@ void LLCoprocedurePool::coprocedureInvokerCoro(LLCoreHttpUtil::HttpCoroutineAdap LL_INFOS() << "Finished coprocedure(" << coproc->mName << ")" << " in pool \"" << mPoolName << "\"" << LL_ENDL; - ActiveCoproc_t::iterator itActive = mActiveCoprocs.find(coproc->mId); - if (itActive != mActiveCoprocs.end()) - { - mActiveCoprocs.erase(itActive); - } + mActiveCoprocs.erase(itActive); } } } diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp index e76f2a1550..72ff89f33c 100755 --- a/indra/llui/llurlentry.cpp +++ b/indra/llui/llurlentry.cpp @@ -1430,7 +1430,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const return LLTrans::getString("ExperienceNameNull"); } - const LLSD& experience_details = LLExperienceCache::getInstance()->get(experience_id); + const LLSD& experience_details = LLExperienceCache::instance().get(experience_id); if(!experience_details.isUndefined()) { std::string experience_name_string = experience_details[LLExperienceCache::NAME].asString(); @@ -1438,7 +1438,7 @@ std::string LLUrlEntryExperienceProfile::getLabel( const std::string &url, const } addObserver(experience_id_string, url, cb); - LLExperienceCache::getInstance()->get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); + LLExperienceCache::instance().get(experience_id, boost::bind(&LLUrlEntryExperienceProfile::onExperienceDetails, this, _1)); return LLTrans::getString("LoadingData"); } diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index b52ccffed9..219bcf0eb0 100755 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -357,7 +357,7 @@ void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object, LLScriptQueueData* datap = new LLScriptQueueData(getKey().asUUID(), viewer_object->getID(), itemp); - LLExperienceCache::getInstance()->fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(), + LLExperienceCache::instance().fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(), boost::bind(&LLFloaterCompileQueue::requestAsset, datap, _1)); } } diff --git a/indra/newview/llfloaterexperienceprofile.cpp b/indra/newview/llfloaterexperienceprofile.cpp index 8a04f9e4cc..e850be99ab 100644 --- a/indra/newview/llfloaterexperienceprofile.cpp +++ b/indra/newview/llfloaterexperienceprofile.cpp @@ -99,7 +99,7 @@ public: if(params.size() != 2 || params[1].asString() != "profile") return false; - LLExperienceCache::getInstance()->get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); + LLExperienceCache::instance().get(params[0].asUUID(), boost::bind(&LLExperienceHandler::experienceCallback, this, _1)); return true; } @@ -288,8 +288,8 @@ BOOL LLFloaterExperienceProfile::postBuild() if (mExperienceId.notNull()) { - LLExperienceCache::getInstance()->fetch(mExperienceId, true); - LLExperienceCache::getInstance()->get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, + LLExperienceCache::instance().fetch(mExperienceId, true); + LLExperienceCache::instance().get(mExperienceId, boost::bind(&LLFloaterExperienceProfile::experienceCallback, getDerivedHandle(), _1)); LLViewerRegion* region = gAgent.getRegion(); @@ -799,8 +799,8 @@ void LLFloaterExperienceProfile::onSaveComplete( const LLSD& content ) } refreshExperience(*it); - LLExperienceCache::getInstance()->insert(*it); - LLExperienceCache::getInstance()->fetch(id, true); + LLExperienceCache::instance().insert(*it); + LLExperienceCache::instance().fetch(id, true); if(mSaveCompleteAction==VIEW) { diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index a166dda8ee..94f3a45d88 100755 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -3699,7 +3699,7 @@ bool LLPanelRegionExperiences::refreshFromRegion(LLViewerRegion* region) mTrusted->loading(); mTrusted->setReadonly(!allow_modify); - LLExperienceCache::getInstance()->getRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), + LLExperienceCache::instance().getRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle(), _1)); return LLPanelRegionInfo::refreshFromRegion(region); @@ -3727,7 +3727,7 @@ BOOL LLPanelRegionExperiences::sendUpdate() content["blocked"]=addIds(mBlocked); content["trusted"]=addIds(mTrusted); - LLExperienceCache::getInstance()->setRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), + LLExperienceCache::instance().setRegionExperiences(boost::bind(&LLPanelRegionExperiences::regionCapabilityQuery, region, _1), content, boost::bind(&LLPanelRegionExperiences::infoCallback, getDerivedHandle(), _1)); return TRUE; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 714d8d0e8f..1c2340b0ef 100755 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -268,7 +268,7 @@ void LLFloaterReporter::getExperienceInfo(const LLUUID& experience_id) if (LLUUID::null != mExperienceID) { - const LLSD& experience = LLExperienceCache::getInstance()->get(mExperienceID); + const LLSD& experience = LLExperienceCache::instance().get(mExperienceID); std::stringstream desc; if(experience.isDefined()) diff --git a/indra/newview/llpanelexperiencelisteditor.cpp b/indra/newview/llpanelexperiencelisteditor.cpp index 20fe0c52fa..9d52a1906b 100644 --- a/indra/newview/llpanelexperiencelisteditor.cpp +++ b/indra/newview/llpanelexperiencelisteditor.cpp @@ -183,7 +183,7 @@ void LLPanelExperienceListEditor::onItems() columns[0]["value"] = getString("loading"); mItems->addElement(item); - LLExperienceCache::getInstance()->get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, + LLExperienceCache::instance().get(experience, boost::bind(&LLPanelExperienceListEditor::experienceDetailsCallback, getDerivedHandle(), _1)); } diff --git a/indra/newview/llpanelexperiencelog.cpp b/indra/newview/llpanelexperiencelog.cpp index 9329d900b1..d5979b6e96 100644 --- a/indra/newview/llpanelexperiencelog.cpp +++ b/indra/newview/llpanelexperiencelog.cpp @@ -140,7 +140,7 @@ void LLPanelExperienceLog::refresh() } const LLSD event = dayArray[i]; LLUUID id = event[LLExperienceCache::EXPERIENCE_ID].asUUID(); - const LLSD& experience = LLExperienceCache::getInstance()->get(id); + const LLSD& experience = LLExperienceCache::instance().get(id); if(experience.isUndefined()){ waiting = true; waiting_id = id; @@ -168,7 +168,7 @@ void LLPanelExperienceLog::refresh() { mEventList->deleteAllItems(); mEventList->setCommentText(getString("loading")); - LLExperienceCache::getInstance()->get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); + LLExperienceCache::instance().get(waiting_id, boost::bind(&LLPanelExperienceLog::refresh, this)); } else { diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp index db846ffad9..d71ced443b 100644 --- a/indra/newview/llpanelexperiencepicker.cpp +++ b/indra/newview/llpanelexperiencepicker.cpp @@ -130,7 +130,7 @@ void LLPanelExperiencePicker::find() std::string text = getChild(TEXT_EDIT)->getValue().asString(); mQueryID.generate(); - LLExperienceCache::getInstance()->findExperienceByName(text, mCurrentPage, + LLExperienceCache::instance().findExperienceByName(text, mCurrentPage, boost::bind(&LLPanelExperiencePicker::findResults, getDerivedHandle(), mQueryID, _1)); getChild(LIST_RESULTS)->deleteAllItems(); diff --git a/indra/newview/llpanelgroupexperiences.cpp b/indra/newview/llpanelgroupexperiences.cpp index 067f9eb426..9b4c67a120 100644 --- a/indra/newview/llpanelgroupexperiences.cpp +++ b/indra/newview/llpanelgroupexperiences.cpp @@ -73,7 +73,7 @@ void LLPanelGroupExperiences::activate() return; } - LLExperienceCache::getInstance()->getGroupExperiences(getGroupID(), + LLExperienceCache::instance().getGroupExperiences(getGroupID(), boost::bind(&LLPanelGroupExperiences::groupExperiencesResults, getDerivedHandle(), _1)); } diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 8a493b7084..5f029ca6a2 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -1325,7 +1325,7 @@ void LLLiveLSLEditor::buildExperienceList() position = ADD_TOP; } - const LLSD& experience = LLExperienceCache::getInstance()->get(id); + const LLSD& experience = LLExperienceCache::instance().get(id); if(experience.isUndefined()) { mExperiences->add(getString("loading"), id, position); @@ -1344,7 +1344,7 @@ void LLLiveLSLEditor::buildExperienceList() if(!foundAssociated ) { - const LLSD& experience = LLExperienceCache::getInstance()->get(associated); + const LLSD& experience = LLExperienceCache::instance().get(associated); if(experience.isDefined()) { std::string experience_name_string = experience[LLExperienceCache::NAME].asString(); @@ -1365,7 +1365,7 @@ void LLLiveLSLEditor::buildExperienceList() if(last.notNull()) { mExperiences->setEnabled(FALSE); - LLExperienceCache::getInstance()->get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); + LLExperienceCache::instance().get(last, boost::bind(&LLLiveLSLEditor::buildExperienceList, this)); } else { @@ -2038,7 +2038,7 @@ void LLLiveLSLEditor::loadAsset() if(item) { - LLExperienceCache::getInstance()->fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), + LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLLiveLSLEditor::setAssociatedExperience, getDerivedHandle(), _1)); bool isGodlike = gAgent.isGodlike(); diff --git a/indra/newview/llsidepaneliteminfo.cpp b/indra/newview/llsidepaneliteminfo.cpp index ca17fe77b1..12cbff888d 100755 --- a/indra/newview/llsidepaneliteminfo.cpp +++ b/indra/newview/llsidepaneliteminfo.cpp @@ -328,7 +328,7 @@ void LLSidepanelItemInfo::refreshFromItem(LLViewerInventoryItem* item) tb->setText(getString("loading_experience")); tb->setVisible(TRUE); - LLExperienceCache::getInstance()->fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), + LLExperienceCache::instance().fetchAssociatedExperience(item->getParentUUID(), item->getUUID(), boost::bind(&LLSidepanelItemInfo::setAssociatedExperience, getDerivedHandle(), _1)); } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 361cc6c48b..4246f72202 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -2822,7 +2822,7 @@ void LLStartUp::initNameCache() void LLStartUp::initExperiences() { // Should trigger loading the cache. - LLExperienceCache::getInstance()->setCapabilityQuery( + LLExperienceCache::instance().setCapabilityQuery( boost::bind(&LLAgent::getRegionCapability, &gAgent, _1)); LLExperienceLog::instance().initialize(); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 4e1a86bb71..ea8fc07e8a 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -6653,7 +6653,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data) else if(experienceid.notNull()) { payload["experience"]=experienceid; - LLExperienceCache::getInstance()->get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); + LLExperienceCache::instance().get(experienceid, boost::bind(process_script_experience_details, _1, args, payload)); return; } -- cgit v1.3