From a5261a5fa8fad810ecb5c260d92c3e771822bf58 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Tue, 20 Feb 2024 23:46:23 +0100 Subject: Convert BOOL to bool in llui --- indra/newview/llcompilequeue.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview/llcompilequeue.cpp') diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index eb2c156ca5..c93ce2c6a3 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -194,12 +194,12 @@ LLFloaterScriptQueue::~LLFloaterScriptQueue() { } -BOOL LLFloaterScriptQueue::postBuild() +bool LLFloaterScriptQueue::postBuild() { childSetAction("close",onCloseBtn,this); - getChildView("close")->setEnabled(FALSE); + getChildView("close")->setEnabled(false); setVisible(true); - return TRUE; + return true; } // static -- cgit v1.2.3 From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llcompilequeue.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'indra/newview/llcompilequeue.cpp') diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index c93ce2c6a3..5fcdbe4ffe 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -215,7 +215,7 @@ void LLFloaterScriptQueue::addObject(const LLUUID& id, std::string name) mObjectList.push_back(obj); } -BOOL LLFloaterScriptQueue::start() +bool LLFloaterScriptQueue::start() { std::string buffer; @@ -242,7 +242,7 @@ void LLFloaterScriptQueue::addStringMessage(const std::string &message) } -BOOL LLFloaterScriptQueue::isDone() const +bool LLFloaterScriptQueue::isDone() const { return (mCurrentObjectID.isNull() && (mObjectList.size() == 0)); } @@ -270,7 +270,7 @@ void LLFloaterCompileQueue::experienceIdsReceived( const LLSD& content ) } } -BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const +bool LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const { return mExperienceIds.find(id) != mExperienceIds.end(); } @@ -537,7 +537,7 @@ bool LLFloaterCompileQueue::startQueue() LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url, success, failure); - return TRUE; + return true; } } @@ -638,7 +638,7 @@ bool LLFloaterRunQueue::runObjectScripts(LLHandle hfloater msg->nextBlockFast(_PREHASH_Script); msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); - msg->addBOOLFast(_PREHASH_Running, TRUE); + msg->addBOOLFast(_PREHASH_Running, true); msg->sendReliable(object->getRegion()->getHost()); return true; @@ -695,7 +695,7 @@ bool LLFloaterNotRunQueue::stopObjectScripts(LLHandle hflo msg->nextBlockFast(_PREHASH_Script); msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); - msg->addBOOLFast(_PREHASH_Running, FALSE); + msg->addBOOLFast(_PREHASH_Running, false); msg->sendReliable(object->getRegion()->getHost()); return true; @@ -818,7 +818,7 @@ void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, L } floater->addStringMessage("Done"); - floater->getChildView("close")->setEnabled(TRUE); + floater->getChildView("close")->setEnabled(true); } catch (LLCheckedHandleBase::Stale &) { -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llcompilequeue.cpp | 1652 +++++++++++++++++++------------------- 1 file changed, 826 insertions(+), 826 deletions(-) (limited to 'indra/newview/llcompilequeue.cpp') diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 906c61c535..552ea75559 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -1,826 +1,826 @@ -/** - * @file llcompilequeue.cpp - * @brief LLCompileQueueData class implementation - * - * $LicenseInfo:firstyear=2002&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$ - */ - -/** - * - * Implementation of the script queue which keeps an array of object - * UUIDs and manipulates all of the scripts on each of them. - * - */ - - -#include "llviewerprecompiledheaders.h" - -#include "llcompilequeue.h" - -#include "llagent.h" -#include "llchat.h" -#include "llfloaterreg.h" -#include "llviewerwindow.h" -#include "llviewerobject.h" -#include "llviewerobjectlist.h" -#include "llviewerregion.h" -#include "llviewercontrol.h" -#include "llviewerobject.h" -#include "llviewerregion.h" -#include "llresmgr.h" - -#include "llbutton.h" -#include "lldir.h" -#include "llnotificationsutil.h" -#include "llviewerstats.h" -#include "llfilesystem.h" -#include "lluictrlfactory.h" -#include "lltrans.h" - -#include "llselectmgr.h" -#include "llexperiencecache.h" - -#include "llviewerassetupload.h" -#include "llcorehttputil.h" - -namespace -{ - - const std::string QUEUE_EVENTPUMP_NAME("ScriptActionQueue"); - const F32 QUEUE_INVENTORY_FETCH_TIMEOUT = 300.f; - - // ObjectIventoryFetcher is an adapter between the LLVOInventoryListener::inventoryChanged - // callback mechanism and the LLEventPump coroutine architecture allowing the - // coroutine to wait for the inventory event. - class ObjectInventoryFetcher: public LLVOInventoryListener - { - public: - typedef std::shared_ptr ptr_t; - - ObjectInventoryFetcher(LLEventPump &pump, LLViewerObject* object, void* user_data) : - mPump(pump), - LLVOInventoryListener() - { - registerVOInventoryListener(object, this); - } - - virtual void inventoryChanged(LLViewerObject* object, - LLInventoryObject::object_list_t* inventory, - S32 serial_num, - void* user_data); - - void fetchInventory() - { - requestVOInventory(); - } - - const LLInventoryObject::object_list_t & getInventoryList() const { return mInventoryList; } - - private: - LLInventoryObject::object_list_t mInventoryList; - LLEventPump & mPump; - }; - - class HandleScriptUserData - { - public: - HandleScriptUserData(const std::string &pumpname) : - mPumpname(pumpname) - { } - - const std::string &getPumpName() const { return mPumpname; } - - private: - std::string mPumpname; - }; - - -} - -// *NOTE$: A minor specialization of LLScriptAssetUpload, it does not require a buffer -// (and does not save a buffer to the cache) and it finds the compile queue window and -// displays a compiling message. -class LLQueuedScriptAssetUpload : public LLScriptAssetUpload -{ -public: - LLQueuedScriptAssetUpload(LLUUID taskId, LLUUID itemId, LLUUID assetId, TargetType_t targetType, - bool isRunning, std::string scriptName, LLUUID queueId, LLUUID exerienceId, taskUploadFinish_f finish) : - LLScriptAssetUpload(taskId, itemId, targetType, isRunning, - exerienceId, std::string(), finish, nullptr), - mScriptName(scriptName), - mQueueId(queueId) - { - setAssetId(assetId); - } - - virtual LLSD prepareUpload() - { - /* *NOTE$: The parent class (LLScriptAssetUpload will attempt to save - * the script buffer into to the cache. Since the resource is already in - * the cache we don't want to do that. Just put a compiling message in - * the window and move on - */ - LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance("compile_queue", LLSD(mQueueId)); - if (queue) - { - std::string message = std::string("Compiling \"") + getScriptName() + std::string("\"..."); - - queue->getChild("queue output")->addSimpleElement(message, ADD_BOTTOM); - } - - return LLSDMap("success", LLSD::Boolean(true)); - } - - - std::string getScriptName() const { return mScriptName; } - -private: - void setScriptName(const std::string &scriptName) { mScriptName = scriptName; } - - LLUUID mQueueId; - std::string mScriptName; -}; - -///---------------------------------------------------------------------------- -/// Local function declarations, constants, enums, and typedefs -///---------------------------------------------------------------------------- - -struct LLScriptQueueData -{ - LLUUID mQueueID; - LLUUID mTaskId; - LLPointer mItem; - LLHost mHost; - LLUUID mExperienceId; - std::string mExperiencename; - LLScriptQueueData(const LLUUID& q_id, const LLUUID& task_id, LLInventoryItem* item) : - mQueueID(q_id), mTaskId(task_id), mItem(new LLInventoryItem(item)) {} - -}; - -///---------------------------------------------------------------------------- -/// Class LLFloaterScriptQueue -///---------------------------------------------------------------------------- - -// Default constructor -LLFloaterScriptQueue::LLFloaterScriptQueue(const LLSD& key) : - LLFloater(key), - mDone(false), - mMono(false) -{ - -} - -// Destroys the object -LLFloaterScriptQueue::~LLFloaterScriptQueue() -{ -} - -bool LLFloaterScriptQueue::postBuild() -{ - childSetAction("close",onCloseBtn,this); - getChildView("close")->setEnabled(false); - setVisible(true); - return true; -} - -// static -void LLFloaterScriptQueue::onCloseBtn(void* user_data) -{ - LLFloaterScriptQueue* self = (LLFloaterScriptQueue*)user_data; - self->closeFloater(); -} - -void LLFloaterScriptQueue::addObject(const LLUUID& id, std::string name) -{ - ObjectData obj = { id, name }; - mObjectList.push_back(obj); -} - -bool LLFloaterScriptQueue::start() -{ - std::string buffer; - - LLStringUtil::format_map_t args; - args["[START]"] = mStartString; - args["[COUNT]"] = llformat ("%d", mObjectList.size()); - buffer = getString ("Starting", args); - - getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); - - return startQueue(); -} - -void LLFloaterScriptQueue::addProcessingMessage(const std::string &message, const LLSD &args) -{ - std::string buffer(LLTrans::getString(message, args)); - - getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); -} - -void LLFloaterScriptQueue::addStringMessage(const std::string &message) -{ - getChild("queue output")->addSimpleElement(message, ADD_BOTTOM); -} - - -bool LLFloaterScriptQueue::isDone() const -{ - return (mCurrentObjectID.isNull() && (mObjectList.size() == 0)); -} - -///---------------------------------------------------------------------------- -/// Class LLFloaterCompileQueue -///---------------------------------------------------------------------------- -LLFloaterCompileQueue::LLFloaterCompileQueue(const LLSD& key) - : LLFloaterScriptQueue(key) -{ - setTitle(LLTrans::getString("CompileQueueTitle")); - setStartString(LLTrans::getString("CompileQueueStart")); - -} - -LLFloaterCompileQueue::~LLFloaterCompileQueue() -{ -} - -void LLFloaterCompileQueue::experienceIdsReceived( const LLSD& content ) -{ - for(LLSD::array_const_iterator it = content.beginArray(); it != content.endArray(); ++it) - { - mExperienceIds.insert(it->asUUID()); - } -} - -bool LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const -{ - return mExperienceIds.find(id) != mExperienceIds.end(); -} - -// //Attempt to record this asset ID. If it can not be inserted into the set -// //then it has already been processed so return false. - -void LLFloaterCompileQueue::handleHTTPResponse(std::string pumpName, const LLSD &expresult) -{ - LLEventPumps::instance().post(pumpName, expresult); -} - -// *TODO: handleSCriptRetrieval is passed into the cache via a legacy C function pointer -// future project would be to convert these to C++ callables (std::function<>) so that -// we can use bind and remove the userData parameter. -// -void LLFloaterCompileQueue::handleScriptRetrieval(const LLUUID& assetId, - LLAssetType::EType type, void* userData, S32 status, LLExtStat extStatus) -{ - LLSD result(LLSD::emptyMap()); - - result["asset_id"] = assetId; - if (status) - { - result["error"] = status; - - if (status == LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE) - { - result["message"] = LLTrans::getString("CompileQueueProblemDownloading") + (":"); - result["alert"] = LLTrans::getString("CompileQueueScriptNotFound"); - } - else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) - { - result["message"] = LLTrans::getString("CompileQueueInsufficientPermFor") + (":"); - result["alert"] = LLTrans::getString("CompileQueueInsufficientPermDownload"); - } - else - { - result["message"] = LLTrans::getString("CompileQueueUnknownFailure"); - } - } - - LLEventPumps::instance().post(((HandleScriptUserData *)userData)->getPumpName(), result); - -} - -/*static*/ -void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID parent) -{ - LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance("compile_queue", parent); - if (!queue) - return; - - queue->experienceIdsReceived(result["experience_ids"]); - - // getDerived handle gets a handle that can be resolved to a parent class of the derived object. - LLHandle hFloater(queue->getDerivedHandle()); - - // note subtle difference here: getDerivedHandle in this case is for an LLFloaterCompileQueue - fnQueueAction_t fn = boost::bind(LLFloaterCompileQueue::processScript, - queue->getDerivedHandle(), _1, _2, _3); - - - LLCoros::instance().launch("ScriptQueueCompile", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, - queue->mStartString, - hFloater, - queue->mObjectList, - fn)); - -} - -/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. -/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. -bool LLFloaterCompileQueue::processScript(LLHandle hfloater, - const LLPointer &object, LLInventoryObject* inventory, LLEventPump &pump) -{ - if (LLApp::isExiting()) - { - // Reply from coroutine came on shutdown - // We are quiting, don't start any more coroutines! - return true; - } - - LLSD result; - LLCheckedHandle floater(hfloater); - // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. - // which is caught in objectScriptProcessingQueueCoro - bool monocompile = floater->mMono; - - // Initial test to see if we can (or should) attempt to compile the script. - LLInventoryItem *item = dynamic_cast(inventory); - - if (!item) - { - LL_WARNS("SCRIPTQ") << "item retrieved is not an LLInventoryItem." << LL_ENDL; - return true; - } - - if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) || - !item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID())) - { - std::string buffer = "Skipping: " + item->getName() + "(Permissions)"; - floater->addStringMessage(buffer); - return true; - } - - // Attempt to retrieve the experience - LLUUID experienceId; - { - LLExperienceCache::instance().fetchAssociatedExperience(inventory->getParentUUID(), inventory->getUUID(), - boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _1)); - - result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT, - LLSDMap("timeout", LLSD::Boolean(true))); - - floater.check(); - - if (result.has("timeout")) - { // A timeout filed in the result will always be true if present. - LLStringUtil::format_map_t args; - args["[OBJECT_NAME]"] = inventory->getName(); - std::string buffer = floater->getString("Timeout", args); - floater->addStringMessage(buffer); - return true; - } - - if (result.has(LLExperienceCache::EXPERIENCE_ID)) - { - experienceId = result[LLExperienceCache::EXPERIENCE_ID].asUUID(); - if (!floater->hasExperience(experienceId)) - { - floater->addProcessingMessage("CompileNoExperiencePerm", - LLSDMap("SCRIPT", inventory->getName()) - ("EXPERIENCE", result[LLExperienceCache::NAME].asString())); - return true; - } - } - - } - - if (!gAssetStorage) - { - // viewer likely is shutting down - return true; - } - - { - HandleScriptUserData userData(pump.getName()); - - - // request the asset - gAssetStorage->getInvItemAsset(LLHost(), - gAgent.getID(), - gAgent.getSessionID(), - item->getPermissions().getOwner(), - object->getID(), - item->getUUID(), - item->getAssetUUID(), - item->getType(), - &LLFloaterCompileQueue::handleScriptRetrieval, - &userData); - - result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT, - LLSDMap("timeout", LLSD::Boolean(true))); - } - - if (result.has("timeout")) - { // A timeout filed in the result will always be true if present. - LLStringUtil::format_map_t args; - args["[OBJECT_NAME]"] = inventory->getName(); - std::string buffer = floater->getString("Timeout", args); - floater->addStringMessage(buffer); - return true; - } - - if (result.has("error")) - { - LL_WARNS("SCRIPTQ") << "Inventory fetch returned with error. Code: " << result["error"].asString() << LL_ENDL; - std::string buffer = result["message"].asString() + " " + inventory->getName(); - floater->addStringMessage(buffer); - - if (result.has("alert")) - { - LLSD args; - args["MESSAGE"] = result["alert"].asString(); - LLNotificationsUtil::add("SystemMessage", args); - } - return true; - } - - LLUUID assetId = result["asset_id"]; - - std::string url = object->getRegion()->getCapability("UpdateScriptTask"); - - { - LLResourceUploadInfo::ptr_t uploadInfo(new LLQueuedScriptAssetUpload(object->getID(), - inventory->getUUID(), - assetId, - monocompile ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2, - true, - inventory->getName(), - LLUUID(), - experienceId, - boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _4))); - - LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); - } - - result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT, LLSDMap("timeout", LLSD::Boolean(true))); - - floater.check(); - - if (result.has("timeout")) - { // A timeout filed in the result will always be true if present. - LLStringUtil::format_map_t args; - args["[OBJECT_NAME]"] = inventory->getName(); - std::string buffer = floater->getString("Timeout", args); - floater->addStringMessage(buffer); - return true; - } - - // Bytecode save completed - if (result["compiled"]) - { - std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" succeeded"); - - floater->addStringMessage(buffer); - LL_INFOS() << buffer << LL_ENDL; - } - else - { - LLSD compile_errors = result["errors"]; - std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" failed:"); - floater->addStringMessage(buffer); - for (LLSD::array_const_iterator line = compile_errors.beginArray(); - line < compile_errors.endArray(); line++) - { - std::string str = line->asString(); - str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); - - floater->addStringMessage(str); - } - LL_INFOS() << result["errors"] << LL_ENDL; - } - - return true; -} - -bool LLFloaterCompileQueue::startQueue() -{ - LLViewerRegion* region = gAgent.getRegion(); - if (region) - { - std::string lookup_url = region->getCapability("GetCreatorExperiences"); - if (!lookup_url.empty()) - { - LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t success = - boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, _1, getKey().asUUID()); - - LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t failure = - boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, LLSD(), getKey().asUUID()); - - LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url, - success, failure); - return true; - } - } - - return true; -} - - -///---------------------------------------------------------------------------- -/// Class LLFloaterResetQueue -///---------------------------------------------------------------------------- - -LLFloaterResetQueue::LLFloaterResetQueue(const LLSD& key) - : LLFloaterScriptQueue(key) -{ - setTitle(LLTrans::getString("ResetQueueTitle")); - setStartString(LLTrans::getString("ResetQueueStart")); -} - -LLFloaterResetQueue::~LLFloaterResetQueue() -{ -} - -/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. -/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. -bool LLFloaterResetQueue::resetObjectScripts(LLHandle hfloater, - const LLPointer &object, LLInventoryObject* inventory, LLEventPump &pump) -{ - LLCheckedHandle floater(hfloater); - // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. - // which is caught in objectScriptProcessingQueueCoro - - std::string buffer; - buffer = floater->getString("Resetting") + (": ") + inventory->getName(); - floater->addStringMessage(buffer); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ScriptReset); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); - msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); - msg->sendReliable(object->getRegion()->getHost()); - - return true; -} - -bool LLFloaterResetQueue::startQueue() -{ - // Bind the resetObjectScripts method into a QueueAction function and pass it - // into the object queue processing coroutine. - fnQueueAction_t fn = boost::bind(LLFloaterResetQueue::resetObjectScripts, - getDerivedHandle(), _1, _2, _3); - - LLCoros::instance().launch("ScriptResetQueue", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, - mStartString, - getDerivedHandle(), - mObjectList, - fn)); - - return true; -} - -///---------------------------------------------------------------------------- -/// Class LLFloaterRunQueue -///---------------------------------------------------------------------------- - -LLFloaterRunQueue::LLFloaterRunQueue(const LLSD& key) - : LLFloaterScriptQueue(key) -{ - setTitle(LLTrans::getString("RunQueueTitle")); - setStartString(LLTrans::getString("RunQueueStart")); -} - -LLFloaterRunQueue::~LLFloaterRunQueue() -{ -} - -/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. -/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. -bool LLFloaterRunQueue::runObjectScripts(LLHandle hfloater, - const LLPointer &object, LLInventoryObject* inventory, LLEventPump &pump) -{ - LLCheckedHandle floater(hfloater); - // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. - // which is caught in objectScriptProcessingQueueCoro - - std::string buffer; - buffer = floater->getString("Running") + (": ") + inventory->getName(); - floater->addStringMessage(buffer); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_SetScriptRunning); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); - msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); - msg->addBOOLFast(_PREHASH_Running, true); - msg->sendReliable(object->getRegion()->getHost()); - - return true; -} - -bool LLFloaterRunQueue::startQueue() -{ - LLHandle hFloater(getDerivedHandle()); - fnQueueAction_t fn = boost::bind(LLFloaterRunQueue::runObjectScripts, hFloater, _1, _2, _3); - - LLCoros::instance().launch("ScriptRunQueue", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, - mStartString, - hFloater, - mObjectList, - fn)); - - return true; -} - - -///---------------------------------------------------------------------------- -/// Class LLFloaterNotRunQueue -///---------------------------------------------------------------------------- - -LLFloaterNotRunQueue::LLFloaterNotRunQueue(const LLSD& key) - : LLFloaterScriptQueue(key) -{ - setTitle(LLTrans::getString("NotRunQueueTitle")); - setStartString(LLTrans::getString("NotRunQueueStart")); -} - -LLFloaterNotRunQueue::~LLFloaterNotRunQueue() -{ -} - -/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. -/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. -bool LLFloaterNotRunQueue::stopObjectScripts(LLHandle hfloater, - const LLPointer &object, LLInventoryObject* inventory, LLEventPump &pump) -{ - LLCheckedHandle floater(hfloater); - // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. - // which is caught in objectScriptProcessingQueueCoro - - std::string buffer; - buffer = floater->getString("NotRunning") + (": ") + inventory->getName(); - floater->addStringMessage(buffer); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_SetScriptRunning); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_Script); - msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); - msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); - msg->addBOOLFast(_PREHASH_Running, false); - msg->sendReliable(object->getRegion()->getHost()); - - return true; -} - -bool LLFloaterNotRunQueue::startQueue() -{ - LLHandle hFloater(getDerivedHandle()); - - fnQueueAction_t fn = boost::bind(&LLFloaterNotRunQueue::stopObjectScripts, hFloater, _1, _2, _3); - LLCoros::instance().launch("ScriptQueueNotRun", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, - mStartString, - hFloater, - mObjectList, - fn)); - - return true; -} - -///---------------------------------------------------------------------------- -/// Local function definitions -///---------------------------------------------------------------------------- -void ObjectInventoryFetcher::inventoryChanged(LLViewerObject* object, - LLInventoryObject::object_list_t* inventory, S32 serial_num, void* user_data) -{ - mInventoryList.clear(); - mInventoryList.assign(inventory->begin(), inventory->end()); - - mPump.post(LLSDMap("changed", LLSD::Boolean(true))); - -} - -void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, LLHandle hfloater, - object_data_list_t objectList, fnQueueAction_t func) -{ - LLCoros::set_consuming(true); - LLCheckedHandle floater(hfloater); - // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. - // This is expected if the dialog closes. - LLEventMailDrop maildrop(QUEUE_EVENTPUMP_NAME, true); - - try - { - for (object_data_list_t::iterator itObj(objectList.begin()); (itObj != objectList.end()); ++itObj) - { - bool firstForObject = true; - LLUUID object_id = (*itObj).mObjectId; - LL_INFOS("SCRIPTQ") << "Next object in queue with ID=" << object_id.asString() << LL_ENDL; - - LLPointer obj = gObjectList.findObject(object_id); - LLInventoryObject::object_list_t inventory; - if (obj) - { - ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL)); - - fetcher->fetchInventory(); - - LLStringUtil::format_map_t args; - args["[OBJECT_NAME]"] = (*itObj).mObjectName; - floater->addStringMessage(floater->getString("LoadingObjInv", args)); - - LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, QUEUE_INVENTORY_FETCH_TIMEOUT, - LLSDMap("timeout", LLSD::Boolean(true))); - - if (result.has("timeout")) - { // A timeout filed in the result will always be true if present. - LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() << - ". Skipping to next object." << LL_ENDL; - - LLStringUtil::format_map_t args; - args["[OBJECT_NAME]"] = (*itObj).mObjectName; - floater->addStringMessage(floater->getString("Timeout", args)); - - continue; - } - - inventory.assign(fetcher->getInventoryList().begin(), fetcher->getInventoryList().end()); - } - else - { - LL_WARNS("SCRIPTQ") << "Unable to retrieve object with ID of " << object_id << - ". Skipping to next." << LL_ENDL; - continue; - } - - // TODO: Get the name of the object we are looking at here so that we can display it below. - //std::string objName = (dynamic_cast(obj.get()))->getName(); - LL_DEBUGS("SCRIPTQ") << "Object has " << inventory.size() << " items." << LL_ENDL; - - for (LLInventoryObject::object_list_t::iterator itInv = inventory.begin(); - itInv != inventory.end(); ++itInv) - { - floater.check(); - - // note, we have a smart pointer to the obj above... but if we didn't we'd check that - // it still exists here. - - if (((*itInv)->getType() == LLAssetType::AT_LSL_TEXT)) - { - LL_DEBUGS("SCRIPTQ") << "Inventory item " << (*itInv)->getUUID().asString() << "\"" << (*itInv)->getName() << "\"" << LL_ENDL; - if (firstForObject) - { - //floater->addStringMessage(objName + ":"); - firstForObject = false; - } - - if (!func(obj, (*itInv), maildrop)) - { - continue; - } - } - - // no other explicit suspension point in this loop. func(...) MIGHT suspend - // but offers no guarantee of doing so. - llcoro::suspend(); - } - floater.check(); - } - - floater->addStringMessage("Done"); - floater->getChildView("close")->setEnabled(true); - } - catch (LLCheckedHandleBase::Stale &) - { - // This is expected. It means that floater has been closed before - // processing was completed. - LL_DEBUGS("SCRIPTQ") << "LLExeceptionStaleHandle caught! Floater has most likely been closed." << LL_ENDL; - } -} +/** + * @file llcompilequeue.cpp + * @brief LLCompileQueueData class implementation + * + * $LicenseInfo:firstyear=2002&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$ + */ + +/** + * + * Implementation of the script queue which keeps an array of object + * UUIDs and manipulates all of the scripts on each of them. + * + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llcompilequeue.h" + +#include "llagent.h" +#include "llchat.h" +#include "llfloaterreg.h" +#include "llviewerwindow.h" +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llviewercontrol.h" +#include "llviewerobject.h" +#include "llviewerregion.h" +#include "llresmgr.h" + +#include "llbutton.h" +#include "lldir.h" +#include "llnotificationsutil.h" +#include "llviewerstats.h" +#include "llfilesystem.h" +#include "lluictrlfactory.h" +#include "lltrans.h" + +#include "llselectmgr.h" +#include "llexperiencecache.h" + +#include "llviewerassetupload.h" +#include "llcorehttputil.h" + +namespace +{ + + const std::string QUEUE_EVENTPUMP_NAME("ScriptActionQueue"); + const F32 QUEUE_INVENTORY_FETCH_TIMEOUT = 300.f; + + // ObjectIventoryFetcher is an adapter between the LLVOInventoryListener::inventoryChanged + // callback mechanism and the LLEventPump coroutine architecture allowing the + // coroutine to wait for the inventory event. + class ObjectInventoryFetcher: public LLVOInventoryListener + { + public: + typedef std::shared_ptr ptr_t; + + ObjectInventoryFetcher(LLEventPump &pump, LLViewerObject* object, void* user_data) : + mPump(pump), + LLVOInventoryListener() + { + registerVOInventoryListener(object, this); + } + + virtual void inventoryChanged(LLViewerObject* object, + LLInventoryObject::object_list_t* inventory, + S32 serial_num, + void* user_data); + + void fetchInventory() + { + requestVOInventory(); + } + + const LLInventoryObject::object_list_t & getInventoryList() const { return mInventoryList; } + + private: + LLInventoryObject::object_list_t mInventoryList; + LLEventPump & mPump; + }; + + class HandleScriptUserData + { + public: + HandleScriptUserData(const std::string &pumpname) : + mPumpname(pumpname) + { } + + const std::string &getPumpName() const { return mPumpname; } + + private: + std::string mPumpname; + }; + + +} + +// *NOTE$: A minor specialization of LLScriptAssetUpload, it does not require a buffer +// (and does not save a buffer to the cache) and it finds the compile queue window and +// displays a compiling message. +class LLQueuedScriptAssetUpload : public LLScriptAssetUpload +{ +public: + LLQueuedScriptAssetUpload(LLUUID taskId, LLUUID itemId, LLUUID assetId, TargetType_t targetType, + bool isRunning, std::string scriptName, LLUUID queueId, LLUUID exerienceId, taskUploadFinish_f finish) : + LLScriptAssetUpload(taskId, itemId, targetType, isRunning, + exerienceId, std::string(), finish, nullptr), + mScriptName(scriptName), + mQueueId(queueId) + { + setAssetId(assetId); + } + + virtual LLSD prepareUpload() + { + /* *NOTE$: The parent class (LLScriptAssetUpload will attempt to save + * the script buffer into to the cache. Since the resource is already in + * the cache we don't want to do that. Just put a compiling message in + * the window and move on + */ + LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance("compile_queue", LLSD(mQueueId)); + if (queue) + { + std::string message = std::string("Compiling \"") + getScriptName() + std::string("\"..."); + + queue->getChild("queue output")->addSimpleElement(message, ADD_BOTTOM); + } + + return LLSDMap("success", LLSD::Boolean(true)); + } + + + std::string getScriptName() const { return mScriptName; } + +private: + void setScriptName(const std::string &scriptName) { mScriptName = scriptName; } + + LLUUID mQueueId; + std::string mScriptName; +}; + +///---------------------------------------------------------------------------- +/// Local function declarations, constants, enums, and typedefs +///---------------------------------------------------------------------------- + +struct LLScriptQueueData +{ + LLUUID mQueueID; + LLUUID mTaskId; + LLPointer mItem; + LLHost mHost; + LLUUID mExperienceId; + std::string mExperiencename; + LLScriptQueueData(const LLUUID& q_id, const LLUUID& task_id, LLInventoryItem* item) : + mQueueID(q_id), mTaskId(task_id), mItem(new LLInventoryItem(item)) {} + +}; + +///---------------------------------------------------------------------------- +/// Class LLFloaterScriptQueue +///---------------------------------------------------------------------------- + +// Default constructor +LLFloaterScriptQueue::LLFloaterScriptQueue(const LLSD& key) : + LLFloater(key), + mDone(false), + mMono(false) +{ + +} + +// Destroys the object +LLFloaterScriptQueue::~LLFloaterScriptQueue() +{ +} + +bool LLFloaterScriptQueue::postBuild() +{ + childSetAction("close",onCloseBtn,this); + getChildView("close")->setEnabled(false); + setVisible(true); + return true; +} + +// static +void LLFloaterScriptQueue::onCloseBtn(void* user_data) +{ + LLFloaterScriptQueue* self = (LLFloaterScriptQueue*)user_data; + self->closeFloater(); +} + +void LLFloaterScriptQueue::addObject(const LLUUID& id, std::string name) +{ + ObjectData obj = { id, name }; + mObjectList.push_back(obj); +} + +bool LLFloaterScriptQueue::start() +{ + std::string buffer; + + LLStringUtil::format_map_t args; + args["[START]"] = mStartString; + args["[COUNT]"] = llformat ("%d", mObjectList.size()); + buffer = getString ("Starting", args); + + getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); + + return startQueue(); +} + +void LLFloaterScriptQueue::addProcessingMessage(const std::string &message, const LLSD &args) +{ + std::string buffer(LLTrans::getString(message, args)); + + getChild("queue output")->addSimpleElement(buffer, ADD_BOTTOM); +} + +void LLFloaterScriptQueue::addStringMessage(const std::string &message) +{ + getChild("queue output")->addSimpleElement(message, ADD_BOTTOM); +} + + +bool LLFloaterScriptQueue::isDone() const +{ + return (mCurrentObjectID.isNull() && (mObjectList.size() == 0)); +} + +///---------------------------------------------------------------------------- +/// Class LLFloaterCompileQueue +///---------------------------------------------------------------------------- +LLFloaterCompileQueue::LLFloaterCompileQueue(const LLSD& key) + : LLFloaterScriptQueue(key) +{ + setTitle(LLTrans::getString("CompileQueueTitle")); + setStartString(LLTrans::getString("CompileQueueStart")); + +} + +LLFloaterCompileQueue::~LLFloaterCompileQueue() +{ +} + +void LLFloaterCompileQueue::experienceIdsReceived( const LLSD& content ) +{ + for(LLSD::array_const_iterator it = content.beginArray(); it != content.endArray(); ++it) + { + mExperienceIds.insert(it->asUUID()); + } +} + +bool LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const +{ + return mExperienceIds.find(id) != mExperienceIds.end(); +} + +// //Attempt to record this asset ID. If it can not be inserted into the set +// //then it has already been processed so return false. + +void LLFloaterCompileQueue::handleHTTPResponse(std::string pumpName, const LLSD &expresult) +{ + LLEventPumps::instance().post(pumpName, expresult); +} + +// *TODO: handleSCriptRetrieval is passed into the cache via a legacy C function pointer +// future project would be to convert these to C++ callables (std::function<>) so that +// we can use bind and remove the userData parameter. +// +void LLFloaterCompileQueue::handleScriptRetrieval(const LLUUID& assetId, + LLAssetType::EType type, void* userData, S32 status, LLExtStat extStatus) +{ + LLSD result(LLSD::emptyMap()); + + result["asset_id"] = assetId; + if (status) + { + result["error"] = status; + + if (status == LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE) + { + result["message"] = LLTrans::getString("CompileQueueProblemDownloading") + (":"); + result["alert"] = LLTrans::getString("CompileQueueScriptNotFound"); + } + else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) + { + result["message"] = LLTrans::getString("CompileQueueInsufficientPermFor") + (":"); + result["alert"] = LLTrans::getString("CompileQueueInsufficientPermDownload"); + } + else + { + result["message"] = LLTrans::getString("CompileQueueUnknownFailure"); + } + } + + LLEventPumps::instance().post(((HandleScriptUserData *)userData)->getPumpName(), result); + +} + +/*static*/ +void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID parent) +{ + LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance("compile_queue", parent); + if (!queue) + return; + + queue->experienceIdsReceived(result["experience_ids"]); + + // getDerived handle gets a handle that can be resolved to a parent class of the derived object. + LLHandle hFloater(queue->getDerivedHandle()); + + // note subtle difference here: getDerivedHandle in this case is for an LLFloaterCompileQueue + fnQueueAction_t fn = boost::bind(LLFloaterCompileQueue::processScript, + queue->getDerivedHandle(), _1, _2, _3); + + + LLCoros::instance().launch("ScriptQueueCompile", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, + queue->mStartString, + hFloater, + queue->mObjectList, + fn)); + +} + +/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. +/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. +bool LLFloaterCompileQueue::processScript(LLHandle hfloater, + const LLPointer &object, LLInventoryObject* inventory, LLEventPump &pump) +{ + if (LLApp::isExiting()) + { + // Reply from coroutine came on shutdown + // We are quiting, don't start any more coroutines! + return true; + } + + LLSD result; + LLCheckedHandle floater(hfloater); + // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. + // which is caught in objectScriptProcessingQueueCoro + bool monocompile = floater->mMono; + + // Initial test to see if we can (or should) attempt to compile the script. + LLInventoryItem *item = dynamic_cast(inventory); + + if (!item) + { + LL_WARNS("SCRIPTQ") << "item retrieved is not an LLInventoryItem." << LL_ENDL; + return true; + } + + if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) || + !item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID())) + { + std::string buffer = "Skipping: " + item->getName() + "(Permissions)"; + floater->addStringMessage(buffer); + return true; + } + + // Attempt to retrieve the experience + LLUUID experienceId; + { + LLExperienceCache::instance().fetchAssociatedExperience(inventory->getParentUUID(), inventory->getUUID(), + boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _1)); + + result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT, + LLSDMap("timeout", LLSD::Boolean(true))); + + floater.check(); + + if (result.has("timeout")) + { // A timeout filed in the result will always be true if present. + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = inventory->getName(); + std::string buffer = floater->getString("Timeout", args); + floater->addStringMessage(buffer); + return true; + } + + if (result.has(LLExperienceCache::EXPERIENCE_ID)) + { + experienceId = result[LLExperienceCache::EXPERIENCE_ID].asUUID(); + if (!floater->hasExperience(experienceId)) + { + floater->addProcessingMessage("CompileNoExperiencePerm", + LLSDMap("SCRIPT", inventory->getName()) + ("EXPERIENCE", result[LLExperienceCache::NAME].asString())); + return true; + } + } + + } + + if (!gAssetStorage) + { + // viewer likely is shutting down + return true; + } + + { + HandleScriptUserData userData(pump.getName()); + + + // request the asset + gAssetStorage->getInvItemAsset(LLHost(), + gAgent.getID(), + gAgent.getSessionID(), + item->getPermissions().getOwner(), + object->getID(), + item->getUUID(), + item->getAssetUUID(), + item->getType(), + &LLFloaterCompileQueue::handleScriptRetrieval, + &userData); + + result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT, + LLSDMap("timeout", LLSD::Boolean(true))); + } + + if (result.has("timeout")) + { // A timeout filed in the result will always be true if present. + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = inventory->getName(); + std::string buffer = floater->getString("Timeout", args); + floater->addStringMessage(buffer); + return true; + } + + if (result.has("error")) + { + LL_WARNS("SCRIPTQ") << "Inventory fetch returned with error. Code: " << result["error"].asString() << LL_ENDL; + std::string buffer = result["message"].asString() + " " + inventory->getName(); + floater->addStringMessage(buffer); + + if (result.has("alert")) + { + LLSD args; + args["MESSAGE"] = result["alert"].asString(); + LLNotificationsUtil::add("SystemMessage", args); + } + return true; + } + + LLUUID assetId = result["asset_id"]; + + std::string url = object->getRegion()->getCapability("UpdateScriptTask"); + + { + LLResourceUploadInfo::ptr_t uploadInfo(new LLQueuedScriptAssetUpload(object->getID(), + inventory->getUUID(), + assetId, + monocompile ? LLScriptAssetUpload::MONO : LLScriptAssetUpload::LSL2, + true, + inventory->getName(), + LLUUID(), + experienceId, + boost::bind(&LLFloaterCompileQueue::handleHTTPResponse, pump.getName(), _4))); + + LLViewerAssetUpload::EnqueueInventoryUpload(url, uploadInfo); + } + + result = llcoro::suspendUntilEventOnWithTimeout(pump, QUEUE_INVENTORY_FETCH_TIMEOUT, LLSDMap("timeout", LLSD::Boolean(true))); + + floater.check(); + + if (result.has("timeout")) + { // A timeout filed in the result will always be true if present. + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = inventory->getName(); + std::string buffer = floater->getString("Timeout", args); + floater->addStringMessage(buffer); + return true; + } + + // Bytecode save completed + if (result["compiled"]) + { + std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" succeeded"); + + floater->addStringMessage(buffer); + LL_INFOS() << buffer << LL_ENDL; + } + else + { + LLSD compile_errors = result["errors"]; + std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" failed:"); + floater->addStringMessage(buffer); + for (LLSD::array_const_iterator line = compile_errors.beginArray(); + line < compile_errors.endArray(); line++) + { + std::string str = line->asString(); + str.erase(std::remove(str.begin(), str.end(), '\n'), str.end()); + + floater->addStringMessage(str); + } + LL_INFOS() << result["errors"] << LL_ENDL; + } + + return true; +} + +bool LLFloaterCompileQueue::startQueue() +{ + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + std::string lookup_url = region->getCapability("GetCreatorExperiences"); + if (!lookup_url.empty()) + { + LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t success = + boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, _1, getKey().asUUID()); + + LLCoreHttpUtil::HttpCoroutineAdapter::completionCallback_t failure = + boost::bind(&LLFloaterCompileQueue::processExperienceIdResults, LLSD(), getKey().asUUID()); + + LLCoreHttpUtil::HttpCoroutineAdapter::callbackHttpGet(lookup_url, + success, failure); + return true; + } + } + + return true; +} + + +///---------------------------------------------------------------------------- +/// Class LLFloaterResetQueue +///---------------------------------------------------------------------------- + +LLFloaterResetQueue::LLFloaterResetQueue(const LLSD& key) + : LLFloaterScriptQueue(key) +{ + setTitle(LLTrans::getString("ResetQueueTitle")); + setStartString(LLTrans::getString("ResetQueueStart")); +} + +LLFloaterResetQueue::~LLFloaterResetQueue() +{ +} + +/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. +/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. +bool LLFloaterResetQueue::resetObjectScripts(LLHandle hfloater, + const LLPointer &object, LLInventoryObject* inventory, LLEventPump &pump) +{ + LLCheckedHandle floater(hfloater); + // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. + // which is caught in objectScriptProcessingQueueCoro + + std::string buffer; + buffer = floater->getString("Resetting") + (": ") + inventory->getName(); + floater->addStringMessage(buffer); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ScriptReset); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Script); + msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); + msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); + msg->sendReliable(object->getRegion()->getHost()); + + return true; +} + +bool LLFloaterResetQueue::startQueue() +{ + // Bind the resetObjectScripts method into a QueueAction function and pass it + // into the object queue processing coroutine. + fnQueueAction_t fn = boost::bind(LLFloaterResetQueue::resetObjectScripts, + getDerivedHandle(), _1, _2, _3); + + LLCoros::instance().launch("ScriptResetQueue", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, + mStartString, + getDerivedHandle(), + mObjectList, + fn)); + + return true; +} + +///---------------------------------------------------------------------------- +/// Class LLFloaterRunQueue +///---------------------------------------------------------------------------- + +LLFloaterRunQueue::LLFloaterRunQueue(const LLSD& key) + : LLFloaterScriptQueue(key) +{ + setTitle(LLTrans::getString("RunQueueTitle")); + setStartString(LLTrans::getString("RunQueueStart")); +} + +LLFloaterRunQueue::~LLFloaterRunQueue() +{ +} + +/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. +/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. +bool LLFloaterRunQueue::runObjectScripts(LLHandle hfloater, + const LLPointer &object, LLInventoryObject* inventory, LLEventPump &pump) +{ + LLCheckedHandle floater(hfloater); + // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. + // which is caught in objectScriptProcessingQueueCoro + + std::string buffer; + buffer = floater->getString("Running") + (": ") + inventory->getName(); + floater->addStringMessage(buffer); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_SetScriptRunning); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Script); + msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); + msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); + msg->addBOOLFast(_PREHASH_Running, true); + msg->sendReliable(object->getRegion()->getHost()); + + return true; +} + +bool LLFloaterRunQueue::startQueue() +{ + LLHandle hFloater(getDerivedHandle()); + fnQueueAction_t fn = boost::bind(LLFloaterRunQueue::runObjectScripts, hFloater, _1, _2, _3); + + LLCoros::instance().launch("ScriptRunQueue", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, + mStartString, + hFloater, + mObjectList, + fn)); + + return true; +} + + +///---------------------------------------------------------------------------- +/// Class LLFloaterNotRunQueue +///---------------------------------------------------------------------------- + +LLFloaterNotRunQueue::LLFloaterNotRunQueue(const LLSD& key) + : LLFloaterScriptQueue(key) +{ + setTitle(LLTrans::getString("NotRunQueueTitle")); + setStartString(LLTrans::getString("NotRunQueueStart")); +} + +LLFloaterNotRunQueue::~LLFloaterNotRunQueue() +{ +} + +/// This is a utility function to be bound and called from objectScriptProcessingQueueCoro. +/// Do not call directly. It may throw a LLCheckedHandle<>::Stale exception. +bool LLFloaterNotRunQueue::stopObjectScripts(LLHandle hfloater, + const LLPointer &object, LLInventoryObject* inventory, LLEventPump &pump) +{ + LLCheckedHandle floater(hfloater); + // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. + // which is caught in objectScriptProcessingQueueCoro + + std::string buffer; + buffer = floater->getString("NotRunning") + (": ") + inventory->getName(); + floater->addStringMessage(buffer); + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_SetScriptRunning); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_Script); + msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); + msg->addUUIDFast(_PREHASH_ItemID, inventory->getUUID()); + msg->addBOOLFast(_PREHASH_Running, false); + msg->sendReliable(object->getRegion()->getHost()); + + return true; +} + +bool LLFloaterNotRunQueue::startQueue() +{ + LLHandle hFloater(getDerivedHandle()); + + fnQueueAction_t fn = boost::bind(&LLFloaterNotRunQueue::stopObjectScripts, hFloater, _1, _2, _3); + LLCoros::instance().launch("ScriptQueueNotRun", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro, + mStartString, + hFloater, + mObjectList, + fn)); + + return true; +} + +///---------------------------------------------------------------------------- +/// Local function definitions +///---------------------------------------------------------------------------- +void ObjectInventoryFetcher::inventoryChanged(LLViewerObject* object, + LLInventoryObject::object_list_t* inventory, S32 serial_num, void* user_data) +{ + mInventoryList.clear(); + mInventoryList.assign(inventory->begin(), inventory->end()); + + mPump.post(LLSDMap("changed", LLSD::Boolean(true))); + +} + +void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, LLHandle hfloater, + object_data_list_t objectList, fnQueueAction_t func) +{ + LLCoros::set_consuming(true); + LLCheckedHandle floater(hfloater); + // Dereferencing floater may fail. If they do they throw LLExeceptionStaleHandle. + // This is expected if the dialog closes. + LLEventMailDrop maildrop(QUEUE_EVENTPUMP_NAME, true); + + try + { + for (object_data_list_t::iterator itObj(objectList.begin()); (itObj != objectList.end()); ++itObj) + { + bool firstForObject = true; + LLUUID object_id = (*itObj).mObjectId; + LL_INFOS("SCRIPTQ") << "Next object in queue with ID=" << object_id.asString() << LL_ENDL; + + LLPointer obj = gObjectList.findObject(object_id); + LLInventoryObject::object_list_t inventory; + if (obj) + { + ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL)); + + fetcher->fetchInventory(); + + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = (*itObj).mObjectName; + floater->addStringMessage(floater->getString("LoadingObjInv", args)); + + LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, QUEUE_INVENTORY_FETCH_TIMEOUT, + LLSDMap("timeout", LLSD::Boolean(true))); + + if (result.has("timeout")) + { // A timeout filed in the result will always be true if present. + LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() << + ". Skipping to next object." << LL_ENDL; + + LLStringUtil::format_map_t args; + args["[OBJECT_NAME]"] = (*itObj).mObjectName; + floater->addStringMessage(floater->getString("Timeout", args)); + + continue; + } + + inventory.assign(fetcher->getInventoryList().begin(), fetcher->getInventoryList().end()); + } + else + { + LL_WARNS("SCRIPTQ") << "Unable to retrieve object with ID of " << object_id << + ". Skipping to next." << LL_ENDL; + continue; + } + + // TODO: Get the name of the object we are looking at here so that we can display it below. + //std::string objName = (dynamic_cast(obj.get()))->getName(); + LL_DEBUGS("SCRIPTQ") << "Object has " << inventory.size() << " items." << LL_ENDL; + + for (LLInventoryObject::object_list_t::iterator itInv = inventory.begin(); + itInv != inventory.end(); ++itInv) + { + floater.check(); + + // note, we have a smart pointer to the obj above... but if we didn't we'd check that + // it still exists here. + + if (((*itInv)->getType() == LLAssetType::AT_LSL_TEXT)) + { + LL_DEBUGS("SCRIPTQ") << "Inventory item " << (*itInv)->getUUID().asString() << "\"" << (*itInv)->getName() << "\"" << LL_ENDL; + if (firstForObject) + { + //floater->addStringMessage(objName + ":"); + firstForObject = false; + } + + if (!func(obj, (*itInv), maildrop)) + { + continue; + } + } + + // no other explicit suspension point in this loop. func(...) MIGHT suspend + // but offers no guarantee of doing so. + llcoro::suspend(); + } + floater.check(); + } + + floater->addStringMessage("Done"); + floater->getChildView("close")->setEnabled(true); + } + catch (LLCheckedHandleBase::Stale &) + { + // This is expected. It means that floater has been closed before + // processing was completed. + LL_DEBUGS("SCRIPTQ") << "LLExeceptionStaleHandle caught! Floater has most likely been closed." << LL_ENDL; + } +} -- cgit v1.2.3