summaryrefslogtreecommitdiff
path: root/indra/newview/llcompilequeue.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llcompilequeue.cpp')
-rw-r--r--[-rwxr-xr-x]indra/newview/llcompilequeue.cpp1069
1 files changed, 609 insertions, 460 deletions
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index d9fd4509a5..7721e67290 100755..100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -37,8 +37,6 @@
#include "llcompilequeue.h"
#include "llagent.h"
-#include "llassetuploadqueue.h"
-#include "llassetuploadresponders.h"
#include "llchat.h"
#include "llfloaterreg.h"
#include "llviewerwindow.h"
@@ -59,11 +57,105 @@
#include "lltrans.h"
#include "llselectmgr.h"
-#include "llexperienceassociationresponder.h"
#include "llexperiencecache.h"
-// *TODO: This should be separated into the script queue, and the floater views of that queue.
-// There should only be one floater class that can view any queue type
+#include "llviewerassetupload.h"
+#include "llcorehttputil.h"
+
+namespace
+{
+
+ const std::string QUEUE_EVENTPUMP_NAME("ScriptActionQueue");
+
+
+ class ObjectInventoryFetcher: public LLVOInventoryListener
+ {
+ public:
+ typedef boost::shared_ptr<ObjectInventoryFetcher> 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 vFS) 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),
+ mScriptName(scriptName),
+ mQueueId(queueId)
+ {
+ setAssetId(assetId);
+ }
+
+ virtual LLSD prepareUpload()
+ {
+ /* *NOTE$: The parent class (LLScriptAssetUpload will attempt to save
+ * the script buffer into to the VFS. Since the resource is already in
+ * the VFS we don't want to do that. Just put a compiling message in
+ * the window and move on
+ */
+ LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(mQueueId));
+ if (queue)
+ {
+ std::string message = std::string("Compiling \"") + getScriptName() + std::string("\"...");
+
+ queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
+ }
+
+ return LLSD().with("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
@@ -108,47 +200,6 @@ BOOL LLFloaterScriptQueue::postBuild()
return TRUE;
}
-// This is the callback method for the viewer object currently being
-// worked on.
-// NOT static, virtual!
-void LLFloaterScriptQueue::inventoryChanged(LLViewerObject* viewer_object,
- LLInventoryObject::object_list_t* inv,
- S32,
- void* q_id)
-{
- LL_INFOS() << "LLFloaterScriptQueue::inventoryChanged() for object "
- << viewer_object->getID() << LL_ENDL;
-
- //Remove this listener from the object since its
- //listener callback is now being executed.
-
- //We remove the listener here because the function
- //removeVOInventoryListener removes the listener from a ViewerObject
- //which it internally stores.
-
- //If we call this further down in the function, calls to handleInventory
- //and nextObject may update the interally stored viewer object causing
- //the removal of the incorrect listener from an incorrect object.
-
- //Fixes SL-6119:Recompile scripts fails to complete
- removeVOInventoryListener();
-
- if (viewer_object && inv && (viewer_object->getID() == mCurrentObjectID) )
- {
- handleInventory(viewer_object, inv);
- }
- else
- {
- // something went wrong...
- // note that we're not working on this one, and move onto the
- // next object in the list.
- LL_WARNS() << "No inventory for " << mCurrentObjectID
- << LL_ENDL;
- nextObject();
- }
-}
-
-
// static
void LLFloaterScriptQueue::onCloseBtn(void* user_data)
{
@@ -156,9 +207,10 @@ void LLFloaterScriptQueue::onCloseBtn(void* user_data)
self->closeFloater();
}
-void LLFloaterScriptQueue::addObject(const LLUUID& id)
+void LLFloaterScriptQueue::addObject(const LLUUID& id, std::string name)
{
- mObjectIDs.push_back(id);
+ ObjectData obj = { id, name };
+ mObjectList.push_back(obj);
}
BOOL LLFloaterScriptQueue::start()
@@ -167,7 +219,7 @@ BOOL LLFloaterScriptQueue::start()
LLStringUtil::format_map_t args;
args["[START]"] = mStartString;
- args["[COUNT]"] = llformat ("%d", mObjectIDs.size());
+ args["[COUNT]"] = llformat ("%d", mObjectList.size());
buffer = getString ("Starting", args);
getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
@@ -175,148 +227,34 @@ BOOL LLFloaterScriptQueue::start()
return startQueue();
}
-BOOL LLFloaterScriptQueue::isDone() const
+void LLFloaterScriptQueue::addProcessingMessage(const std::string &message, const LLSD &args)
{
- return (mCurrentObjectID.isNull() && (mObjectIDs.size() == 0));
-}
+ std::string buffer(LLTrans::getString(message, args));
-// go to the next object. If no objects left, it falls out silently
-// and waits to be killed by the window being closed.
-BOOL LLFloaterScriptQueue::nextObject()
-{
- U32 count;
- BOOL successful_start = FALSE;
- do
- {
- count = mObjectIDs.size();
- LL_INFOS() << "LLFloaterScriptQueue::nextObject() - " << count
- << " objects left to process." << LL_ENDL;
- mCurrentObjectID.setNull();
- if(count > 0)
- {
- successful_start = popNext();
- }
- LL_INFOS() << "LLFloaterScriptQueue::nextObject() "
- << (successful_start ? "successful" : "unsuccessful")
- << LL_ENDL;
- } while((mObjectIDs.size() > 0) && !successful_start);
- if(isDone() && !mDone)
- {
- mDone = true;
- getChild<LLScrollListCtrl>("queue output")->addSimpleElement(getString("Done"), ADD_BOTTOM);
- getChildView("close")->setEnabled(TRUE);
- }
- return successful_start;
+ getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
}
-// returns true if the queue has started, otherwise false. This
-// method pops the top object off of the queue.
-BOOL LLFloaterScriptQueue::popNext()
+void LLFloaterScriptQueue::addStringMessage(const std::string &message)
{
- // get the first element off of the container, and attempt to get
- // the inventory.
- BOOL rv = FALSE;
- S32 count = mObjectIDs.size();
- if(mCurrentObjectID.isNull() && (count > 0))
- {
- mCurrentObjectID = mObjectIDs.at(0);
- LL_INFOS() << "LLFloaterScriptQueue::popNext() - mCurrentID: "
- << mCurrentObjectID << LL_ENDL;
- mObjectIDs.erase(mObjectIDs.begin());
- LLViewerObject* obj = gObjectList.findObject(mCurrentObjectID);
- if(obj)
- {
- LL_INFOS() << "LLFloaterScriptQueue::popNext() requesting inv for "
- << mCurrentObjectID << LL_ENDL;
- LLUUID* id = new LLUUID(getKey().asUUID());
- registerVOInventoryListener(obj,id);
- requestVOInventory();
- rv = TRUE;
- }
- }
- return rv;
+ getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
}
-BOOL LLFloaterScriptQueue::startQueue()
-{
- return nextObject();
-}
-class CompileQueueExperienceResponder : public LLHTTPClient::Responder
+BOOL LLFloaterScriptQueue::isDone() const
{
-public:
- CompileQueueExperienceResponder(const LLUUID& parent):mParent(parent)
- {
- }
-
- LLUUID mParent;
-
- /*virtual*/ void httpSuccess()
- {
- sendResult(getContent());
- }
- /*virtual*/ void httpFailure()
- {
- sendResult(LLSD());
- }
- void sendResult(const LLSD& content)
- {
- LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", mParent);
- if(!queue)
- return;
-
- queue->experienceIdsReceived(content["experience_ids"]);
- }
-};
-
-
-
+ return (mCurrentObjectID.isNull() && (mObjectList.size() == 0));
+}
///----------------------------------------------------------------------------
/// Class LLFloaterCompileQueue
///----------------------------------------------------------------------------
-
-class LLCompileFloaterUploadQueueSupplier : public LLAssetUploadQueueSupplier
-{
-public:
-
- LLCompileFloaterUploadQueueSupplier(const LLUUID& queue_id) :
- mQueueId(queue_id)
- {
- }
-
- virtual LLAssetUploadQueue* get() const
- {
- LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(mQueueId));
- if(NULL == queue)
- {
- return NULL;
- }
- return queue->getUploadQueue();
- }
-
- virtual void log(std::string message) const
- {
- LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", LLSD(mQueueId));
- if(NULL == queue)
- {
- return;
- }
-
- queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(message, ADD_BOTTOM);
- }
-
-private:
- LLUUID mQueueId;
-};
-
LLFloaterCompileQueue::LLFloaterCompileQueue(const LLSD& key)
: LLFloaterScriptQueue(key)
{
setTitle(LLTrans::getString("CompileQueueTitle"));
setStartString(LLTrans::getString("CompileQueueStart"));
- mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(key.asUUID()));
+// mUploadQueue = new LLAssetUploadQueue(new LLCompileFloaterUploadQueueSupplier(key.asUUID()));
}
LLFloaterCompileQueue::~LLFloaterCompileQueue()
@@ -329,7 +267,7 @@ void LLFloaterCompileQueue::experienceIdsReceived( const LLSD& content )
{
mExperienceIds.insert(it->asUUID());
}
- nextObject();
+// nextObject();
}
BOOL LLFloaterCompileQueue::hasExperience( const LLUUID& id ) const
@@ -337,172 +275,289 @@ 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.
+// bool LLFloaterCompileQueue::checkAssetId(const LLUUID &assetId)
+// {
+// std::pair<uuid_list_t::iterator, bool> result = mAssetIds.insert(assetId);
+// return result.second;
+// }
-void LLFloaterCompileQueue::handleInventory(LLViewerObject *viewer_object,
- LLInventoryObject::object_list_t* inv)
+void LLFloaterCompileQueue::handleHTTPResponse(std::string pumpName, const LLSD &expresult)
{
- // find all of the lsl, leaving off duplicates. We'll remove
- // all matching asset uuids on compilation success.
-
- typedef std::multimap<LLUUID, LLPointer<LLInventoryItem> > uuid_item_map;
- uuid_item_map asset_item_map;
+ LLEventPumps::instance().post(pumpName, expresult);
+}
- LLInventoryObject::object_list_t::const_iterator it = inv->begin();
- LLInventoryObject::object_list_t::const_iterator end = inv->end();
- for ( ; it != end; ++it)
- {
- if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
- {
- LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- // Check permissions before allowing the user to retrieve data.
- if (item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) &&
- item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()) )
- {
- LLPointer<LLViewerInventoryItem> script = new LLViewerInventoryItem(item);
- mCurrentScripts.push_back(script);
- asset_item_map.insert(std::make_pair(item->getAssetUUID(), item));
- }
- }
- }
+// *TODO: handleSCriptRetrieval is passed into the VFS 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(LLVFS *vfs, 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);
- if (asset_item_map.empty())
- {
- // There are no scripts in this object. move on.
- nextObject();
- }
- else
- {
- // request all of the assets.
- uuid_item_map::iterator iter;
- for(iter = asset_item_map.begin(); iter != asset_item_map.end(); iter++)
- {
- LLInventoryItem *itemp = iter->second;
- LLScriptQueueData* datap = new LLScriptQueueData(getKey().asUUID(),
- viewer_object->getID(), itemp);
-
- ExperienceAssociationResponder::fetchAssociatedExperience(itemp->getParentUUID(), itemp->getUUID(),
- boost::bind(LLFloaterCompileQueue::requestAsset, datap, _1));
- }
- }
}
-
-void LLFloaterCompileQueue::requestAsset( LLScriptQueueData* datap, const LLSD& experience )
+/*static*/
+void LLFloaterCompileQueue::processExperienceIdResults(LLSD result, LLUUID parent)
{
- LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", datap->mQueueID);
- if(!queue)
- {
- delete datap;
- return;
- }
- if(experience.has(LLExperienceCache::EXPERIENCE_ID))
- {
- datap->mExperienceId=experience[LLExperienceCache::EXPERIENCE_ID].asUUID();
- if(!queue->hasExperience(datap->mExperienceId))
- {
- std::string buffer = LLTrans::getString("CompileNoExperiencePerm", LLSD::emptyMap()
- .with("SCRIPT", datap->mItem->getName())
- .with("EXPERIENCE", experience[LLExperienceCache::NAME].asString()));
-
- queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
- queue->removeItemByItemID(datap->mItem->getUUID());
- delete datap;
- return;
- }
- }
- //LL_INFOS() << "ITEM NAME 2: " << names.get(i) << LL_ENDL;
- gAssetStorage->getInvItemAsset(datap->mHost,
- gAgent.getID(),
- gAgent.getSessionID(),
- datap->mItem->getPermissions().getOwner(),
- datap->mTaskId,
- datap->mItem->getUUID(),
- datap->mItem->getAssetUUID(),
- datap->mItem->getType(),
- LLFloaterCompileQueue::scriptArrived,
- (void*)datap);
+ LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", parent);
+ if (!queue)
+ return;
+
+ queue->experienceIdsReceived(result["experience_ids"]);
+
+ LLHandle<LLFloaterScriptQueue> hFloater(queue->getDerivedHandle<LLFloaterScriptQueue>());
+
+ fnQueueAction_t fn = boost::bind(LLFloaterCompileQueue::processScript,
+ queue->getDerivedHandle<LLFloaterCompileQueue>(), _1, _2, _3);
+
+
+ LLCoros::instance().launch("ScriptQueueCompile", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro,
+ queue->mStartString,
+ hFloater,
+ queue->mObjectList,
+ fn));
+
}
+bool LLFloaterCompileQueue::processScript(LLHandle<LLFloaterCompileQueue> hfloater,
+ const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
+{
+ LLSD result;
+ LLFloaterCompileQueue *that = hfloater.get();
+ bool monocompile = that->mMono;
+ F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout");
+
+ if (!that)
+ return false;
+
+ // Initial test to see if we can (or should) attempt to compile the script.
+ LLInventoryItem *item = dynamic_cast<LLInventoryItem *>(inventory);
+ {
+
+ if (!item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID()) ||
+ !item->getPermissions().allowCopyBy(gAgent.getID(), gAgent.getGroupID()))
+ {
+ std::string buffer = "Skipping: " + item->getName() + "(Permissions)";
+ that->addStringMessage(buffer);
+ return true;
+ }
+
+// if (!that->checkAssetId(item->getAssetUUID()))
+// {
+// std::string buffer = "Skipping: " + item->getName() + "(Repeat)";
+// that->addStringMessage(buffer);
+// return true;
+// }
+ }
+ that = NULL;
+
+ // 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, fetch_timeout,
+ LLSD().with("timeout", LLSD::Boolean(true)));
+
+ that = hfloater.get();
+ if (!that)
+ {
+ return false;
+ }
+
+ if (result.has("timeout") && result["timeout"].asBoolean())
+ {
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = inventory->getName();
+ std::string buffer = that->getString("Timeout", args);
+ that->addStringMessage(buffer);
+ return true;
+ }
+
+ if (result.has(LLExperienceCache::EXPERIENCE_ID))
+ {
+ experienceId = result[LLExperienceCache::EXPERIENCE_ID].asUUID();
+ if (!that->hasExperience(experienceId))
+ {
+ that->addProcessingMessage("CompileNoExperiencePerm", LLSD()
+ .with("SCRIPT", inventory->getName())
+ .with("EXPERIENCE", result[LLExperienceCache::NAME].asString()));
+ return true;
+ }
+ }
+
+ }
+ that = NULL;
+
+ {
+ 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, fetch_timeout,
+ LLSD().with("timeout", LLSD::Boolean(true)));
+ }
+
+ that = hfloater.get();
+ if (!that)
+ {
+ return false;
+ }
+
+ if (result.has("timeout"))
+ {
+ if (result.has("timeout") && result["timeout"].asBoolean())
+ {
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = inventory->getName();
+ std::string buffer = that->getString("Timeout", args);
+ that->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();
+ that->addStringMessage(buffer);
+
+ if (result.has("alert"))
+ {
+ LLSD args;
+ args["MESSAGE"] = result["alert"].asString();
+ LLNotificationsUtil::add("SystemMessage", args);
+ }
+ return true;
+ }
+
+ LLUUID assetId = result["asset_id"];
+ that = NULL;
+
+
+ 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, fetch_timeout, LLSD().with("timeout", LLSD::Boolean(true)));
+
+ that = hfloater.get();
+ if (!that)
+ {
+ return false;
+ }
+
+ if (result.has("timeout"))
+ {
+ if (result.has("timeout") && result["timeout"].asBoolean())
+ {
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = inventory->getName();
+ std::string buffer = that->getString("Timeout", args);
+ that->addStringMessage(buffer);
+ return true;
+ }
+ }
+
+ // Bytecode save completed
+ if (result["compiled"])
+ {
+ std::string buffer = std::string("Compilation of \"") + inventory->getName() + std::string("\" succeeded");
+
+ that->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:");
+ that->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());
+
+ that->addStringMessage(str);
+ }
+ LL_INFOS() << result["errors"] << LL_ENDL;
+ }
+
+ return true;
+}
-// This is the callback for when each script arrives
-// static
-void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id,
- LLAssetType::EType type,
- void* user_data, S32 status, LLExtStat ext_status)
+bool LLFloaterCompileQueue::startQueue()
{
- LL_INFOS() << "LLFloaterCompileQueue::scriptArrived()" << LL_ENDL;
- LLScriptQueueData* data = (LLScriptQueueData*)user_data;
- if(!data)
- {
- return;
- }
- LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance<LLFloaterCompileQueue>("compile_queue", data->mQueueID);
-
- std::string buffer;
- if(queue && (0 == status))
- {
- //LL_INFOS() << "ITEM NAME 3: " << data->mScriptName << LL_ENDL;
-
- // Dump this into a file on the local disk so we can compile it.
- std::string filename;
- LLVFile file(vfs, asset_id, type);
- std::string uuid_str;
- asset_id.toString(uuid_str);
- filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str) + llformat(".%s",LLAssetType::lookup(type));
-
- const bool is_running = true;
- LLViewerObject* object = gObjectList.findObject(data->mTaskId);
- if (object)
- {
- std::string url = object->getRegion()->getCapability("UpdateScriptTask");
- if(!url.empty())
- {
- // Read script source in to buffer.
- U32 script_size = file.getSize();
- U8* script_data = new U8[script_size];
- file.read(script_data, script_size);
-
- queue->mUploadQueue->queue(filename, data->mTaskId,
- data->mItem->getUUID(), is_running, queue->mMono, queue->getKey().asUUID(),
- script_data, script_size, data->mItem->getName(), data->mExperienceId);
- }
- else
- {
- buffer = LLTrans::getString("CompileQueueServiceUnavailable") + (": ") + data->mItem->getName();
- }
- }
- }
- else
- {
- if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status )
- {
- LLSD args;
- args["MESSAGE"] = LLTrans::getString("CompileQueueScriptNotFound");
- LLNotificationsUtil::add("SystemMessage", args);
-
- buffer = LLTrans::getString("CompileQueueProblemDownloading") + (": ") + data->mItem->getName();
- }
- else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
- {
- LLSD args;
- args["MESSAGE"] = LLTrans::getString("CompileQueueInsufficientPermDownload");
- LLNotificationsUtil::add("SystemMessage", args);
-
- buffer = LLTrans::getString("CompileQueueInsufficientPermFor") + (": ") + data->mItem->getName();
- }
- else
- {
- buffer = LLTrans::getString("CompileQueueUnknownFailure") + (" ") + data->mItem->getName();
- }
-
- LL_WARNS() << "Problem downloading script asset." << LL_ENDL;
- if(queue) queue->removeItemByItemID(data->mItem->getUUID());
- }
- if(queue && (buffer.size() > 0))
- {
- queue->getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
- }
- delete data;
+ 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;
}
@@ -521,40 +576,42 @@ LLFloaterResetQueue::~LLFloaterResetQueue()
{
}
-void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv)
+bool LLFloaterResetQueue::resetObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
+ const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
- // find all of the lsl, leaving off duplicates. We'll remove
- // all matching asset uuids on compilation success.
+ LLFloaterScriptQueue *that = hfloater.get();
+ if (that)
+ {
+ std::string buffer;
+ buffer = that->getString("Resetting") + (": ") + inventory->getName();
+ that->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;
+}
- LLInventoryObject::object_list_t::const_iterator it = inv->begin();
- LLInventoryObject::object_list_t::const_iterator end = inv->end();
- for ( ; it != end; ++it)
- {
- if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
- {
- LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
-
- if (object)
- {
- LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- std::string buffer;
- buffer = getString("Resetting") + (": ") + item->getName();
- getChild<LLScrollListCtrl>("queue output")->addSimpleElement(buffer, ADD_BOTTOM);
- 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, viewer_obj->getID());
- msg->addUUIDFast(_PREHASH_ItemID, (*it)->getUUID());
- msg->sendReliable(object->getRegion()->getHost());
- }
- }
- }
+bool LLFloaterResetQueue::startQueue()
+{
+ fnQueueAction_t fn = boost::bind(LLFloaterResetQueue::resetObjectScripts,
+ getDerivedHandle<LLFloaterScriptQueue>(), _1, _2, _3);
+
+ LLCoros::instance().launch("ScriptResetQueue", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro,
+ mStartString,
+ getDerivedHandle<LLFloaterScriptQueue>(),
+ mObjectList,
+ fn));
- nextObject();
+ return true;
}
///----------------------------------------------------------------------------
@@ -572,44 +629,46 @@ LLFloaterRunQueue::~LLFloaterRunQueue()
{
}
-void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv)
+bool LLFloaterRunQueue::runObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
+ const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
- // find all of the lsl, leaving off duplicates. We'll remove
- // all matching asset uuids on compilation success.
- LLInventoryObject::object_list_t::const_iterator it = inv->begin();
- LLInventoryObject::object_list_t::const_iterator end = inv->end();
- for ( ; it != end; ++it)
- {
- if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
- {
- LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
-
- if (object)
- {
- LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
- std::string buffer;
- buffer = getString("Running") + (": ") + item->getName();
- list->addSimpleElement(buffer, ADD_BOTTOM);
-
- 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, viewer_obj->getID());
- msg->addUUIDFast(_PREHASH_ItemID, (*it)->getUUID());
- msg->addBOOLFast(_PREHASH_Running, TRUE);
- msg->sendReliable(object->getRegion()->getHost());
- }
- }
- }
+ LLFloaterScriptQueue *that = hfloater.get();
+ if (that)
+ {
+ std::string buffer;
+ buffer = that->getString("Running") + (": ") + inventory->getName();
+ that->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<LLFloaterScriptQueue> hFloater(getDerivedHandle<LLFloaterScriptQueue>());
+ fnQueueAction_t fn = boost::bind(LLFloaterRunQueue::runObjectScripts, hFloater, _1, _2, _3);
- nextObject();
+ LLCoros::instance().launch("ScriptRunQueue", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro,
+ mStartString,
+ hFloater,
+ mObjectList,
+ fn));
+
+ return true;
}
+
///----------------------------------------------------------------------------
/// Class LLFloaterNotRunQueue
///----------------------------------------------------------------------------
@@ -625,81 +684,171 @@ LLFloaterNotRunQueue::~LLFloaterNotRunQueue()
{
}
-void LLFloaterCompileQueue::removeItemByItemID(const LLUUID& asset_id)
+bool LLFloaterNotRunQueue::stopObjectScripts(LLHandle<LLFloaterScriptQueue> hfloater,
+ const LLPointer<LLViewerObject> &object, LLInventoryObject* inventory, LLEventPump &pump)
{
- LL_INFOS() << "LLFloaterCompileQueue::removeItemByAssetID()" << LL_ENDL;
- for(S32 i = 0; i < mCurrentScripts.size(); )
- {
- if(asset_id == mCurrentScripts.at(i)->getUUID())
- {
- vector_replace_with_last(mCurrentScripts, mCurrentScripts.begin() + i);
- }
- else
- {
- ++i;
- }
- }
- if(mCurrentScripts.empty())
- {
- nextObject();
- }
+ LLFloaterScriptQueue *that = hfloater.get();
+ if (that)
+ {
+ std::string buffer;
+ buffer = that->getString("NotRunning") + (": ") + inventory->getName();
+ that->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 LLFloaterCompileQueue::startQueue()
+bool LLFloaterNotRunQueue::startQueue()
{
- LLViewerRegion* region = gAgent.getRegion();
- if (region)
- {
- std::string lookup_url=region->getCapability("GetCreatorExperiences");
- if(!lookup_url.empty())
- {
- LLHTTPClient::get(lookup_url, new CompileQueueExperienceResponder(getKey().asUUID()));
- return TRUE;
- }
- }
- return nextObject();
-}
+ LLHandle<LLFloaterScriptQueue> hFloater(getDerivedHandle<LLFloaterScriptQueue>());
+ fnQueueAction_t fn = boost::bind(&LLFloaterNotRunQueue::stopObjectScripts, hFloater, _1, _2, _3);
+ LLCoros::instance().launch("ScriptQueueNotRun", boost::bind(LLFloaterScriptQueue::objectScriptProcessingQueueCoro,
+ mStartString,
+ hFloater,
+ mObjectList,
+ fn));
-
-void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj,
- LLInventoryObject::object_list_t* inv)
-{
- // find all of the lsl, leaving off duplicates. We'll remove
- // all matching asset uuids on compilation success.
- LLInventoryObject::object_list_t::const_iterator it = inv->begin();
- LLInventoryObject::object_list_t::const_iterator end = inv->end();
- for ( ; it != end; ++it)
- {
- if((*it)->getType() == LLAssetType::AT_LSL_TEXT)
- {
- LLViewerObject* object = gObjectList.findObject(viewer_obj->getID());
-
- if (object)
- {
- LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it));
- LLScrollListCtrl* list = getChild<LLScrollListCtrl>("queue output");
- std::string buffer;
- buffer = getString("NotRunning") + (": ") +item->getName();
- list->addSimpleElement(buffer, ADD_BOTTOM);
-
- 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, viewer_obj->getID());
- msg->addUUIDFast(_PREHASH_ItemID, (*it)->getUUID());
- msg->addBOOLFast(_PREHASH_Running, FALSE);
- msg->sendReliable(object->getRegion()->getHost());
- }
- }
- }
-
- nextObject();
+ 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(LLSD().with("changed", LLSD::Boolean(true)));
+
+}
+
+void LLFloaterScriptQueue::objectScriptProcessingQueueCoro(std::string action, LLHandle<LLFloaterScriptQueue> hfloater,
+ object_data_list_t objectList, fnQueueAction_t func)
+{
+ LLCoros::set_consuming(true);
+ LLFloaterScriptQueue * floater(NULL);
+ LLEventMailDrop maildrop(QUEUE_EVENTPUMP_NAME, true);
+ F32 fetch_timeout = gSavedSettings.getF32("QueueInventoryFetchTimeout");
+
+// floater = hfloater.get();
+// floater->addProcessingMessage("Starting",
+// LLSD()
+// .with("[START]", action)
+// .with("[COUNT]", LLSD::Integer(objectList.size())));
+// floater = NULL;
+
+ 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<LLViewerObject> obj = gObjectList.findObject(object_id);
+ LLInventoryObject::object_list_t inventory;
+ if (obj)
+ {
+ ObjectInventoryFetcher::ptr_t fetcher(new ObjectInventoryFetcher(maildrop, obj, NULL));
+
+ fetcher->fetchInventory();
+
+ floater = hfloater.get();
+ if (floater)
+ {
+ LLStringUtil::format_map_t args;
+ args["[OBJECT_NAME]"] = (*itObj).mObjectName;
+ floater->addStringMessage(floater->getString("LoadingObjInv", args));
+ }
+
+ LLSD result = llcoro::suspendUntilEventOnWithTimeout(maildrop, fetch_timeout,
+ LLSD().with("timeout", LLSD::Boolean(true)));
+
+ if (result.has("timeout") && result["timeout"].asBoolean())
+ {
+ LL_WARNS("SCRIPTQ") << "Unable to retrieve inventory for object " << object_id.asString() <<
+ ". Skipping to next object." << LL_ENDL;
+
+ // floater could have been closed
+ floater = hfloater.get();
+ if (floater)
+ {
+ 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<LLInventoryObject *>(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 = hfloater.get();
+ if (!floater)
+ {
+ LL_WARNS("SCRIPTQ") << "Script Queue floater closed! Canceling remaining ops" << LL_ENDL;
+ break;
+ }
+
+ // 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;
+ }
+ }
+
+ llcoro::suspend();
+ }
+ // Just test to be sure the floater is still present before calling the func
+ if (!hfloater.get())
+ {
+ LL_WARNS("SCRIPTQ") << "Script Queue floater dismissed." << LL_ENDL;
+ break;
+ }
+
+ }
+
+ floater = hfloater.get();
+ if (floater)
+ {
+ floater->addStringMessage("Done");
+ floater->getChildView("close")->setEnabled(TRUE);
+ }
+}