Match AISAPI refactoring.

This commit is contained in:
Shyotl
2017-03-13 23:58:56 -05:00
parent d42e380698
commit 7dd616357f
7 changed files with 482 additions and 458 deletions

View File

@@ -35,305 +35,314 @@
#include "llviewerregion.h"
#include "llinventoryobserver.h"
#include "llviewercontrol.h"
#include <boost/bind.hpp>
///----------------------------------------------------------------------------
/// Classes for AISv3 support.
///----------------------------------------------------------------------------
// AISCommand - base class for retry-able HTTP requests using the AISv3 cap.
AISCommand::AISCommand(LLPointer<LLInventoryCallback> callback):
mCommandFunc(NULL),
mCallback(callback)
class AISCommand : public LLHTTPClient::ResponderWithResult
{
mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10);
}
bool AISCommand::run_command()
{
if (NULL == mCommandFunc)
{
// This may happen if a command failed to initiate itself.
LL_WARNS("Inventory") << "AIS command attempted with null command function" << LL_ENDL;
return false;
}
else
{
mCommandFunc();
return true;
}
}
void AISCommand::setCommandFunc(command_func_type command_func)
{
mCommandFunc = command_func;
}
public:
typedef boost::function<void()> command_func_type;
// AISCommand - base class for retry-able HTTP requests using the AISv3 cap.
AISCommand(AISAPI::COMMAND_TYPE type, const char* name, const LLUUID& targetId, AISAPI::completion_t callback) :
mCommandFunc(NULL),
mRetryPolicy(new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10)),
mCompletionFunc(callback),
mTargetId(targetId),
mName(name),
mType(type)
{}
// virtual
bool AISCommand::getResponseUUID(const LLSD& content, LLUUID& id)
{
return false;
}
/* virtual */
void AISCommand::httpSuccess()
{
// Command func holds a reference to self, need to release it
// after a success or final failure.
setCommandFunc(no_op);
const LLSD& content = getContent();
if (!content.isMap())
void run( command_func_type func )
{
failureResult(400, "Malformed response contents", content);
return;
(mCommandFunc = func)();
}
mRetryPolicy->onSuccess();
gInventory.onAISUpdateReceived("AISCommand", content);
if (mCallback)
char const* getName(void) const
{
LLUUID id; // will default to null if parse fails.
getResponseUUID(content,id);
mCallback->fire(id);
return mName;
}
}
/*virtual*/
void AISCommand::httpFailure()
{
LL_WARNS("Inventory") << dumpResponse() << LL_ENDL;
S32 status = getStatus();
const AIHTTPReceivedHeaders& headers = getResponseHeaders();
mRetryPolicy->onFailure(status, headers);
F32 seconds_to_wait;
if (mRetryPolicy->shouldRetry(seconds_to_wait))
void markComplete()
{
doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait);
mRetryPolicy->onSuccess();
}
else
protected:
/* virtual */
void httpSuccess()
{
// Command func holds a reference to self, need to release it
// after a success or final failure.
// *TODO: Notify user? This seems bad.
setCommandFunc(no_op);
mCommandFunc = no_op;
AISAPI::InvokeAISCommandCoro(this, getURL(), mTargetId, getContent(), mCompletionFunc, (AISAPI::COMMAND_TYPE)mType);
}
}
//static
bool AISCommand::isAPIAvailable()
/*virtual*/
void httpFailure()
{
LL_WARNS("Inventory") << dumpResponse() << LL_ENDL;
S32 status = getStatus();
const AIHTTPReceivedHeaders& headers = getResponseHeaders();
mRetryPolicy->onFailure(status, headers);
F32 seconds_to_wait;
if (mRetryPolicy->shouldRetry(seconds_to_wait))
{
doAfterInterval(mCommandFunc,seconds_to_wait);
}
else
{
// Command func holds a reference to self, need to release it
// after a success or final failure.
// *TODO: Notify user? This seems bad.
mCommandFunc = no_op;
}
}
command_func_type mCommandFunc;
LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
AISAPI::completion_t mCompletionFunc;
const LLUUID mTargetId;
const char* mName;
AISAPI::COMMAND_TYPE mType;
};
//=========================================================================
const std::string AISAPI::INVENTORY_CAP_NAME("InventoryAPIv3");
const std::string AISAPI::LIBRARY_CAP_NAME("LibraryAPIv3");
//-------------------------------------------------------------------------
/*static*/
bool AISAPI::isAvailable()
{
if (gAgent.getRegion())
{
return gAgent.getRegion()->isCapabilityAvailable("InventoryAPIv3");
return gAgent.getRegion()->isCapabilityAvailable(INVENTORY_CAP_NAME);
}
return false;
}
//static
bool AISCommand::getInvCap(std::string& cap)
/*static*/
void AISAPI::getCapNames(LLSD& capNames)
{
if (gAgent.getRegion())
{
cap = gAgent.getRegion()->getCapability("InventoryAPIv3");
}
if (!cap.empty())
{
return true;
}
return false;
capNames.append(INVENTORY_CAP_NAME);
capNames.append(LIBRARY_CAP_NAME);
}
//static
bool AISCommand::getLibCap(std::string& cap)
/*static*/
std::string AISAPI::getInvCap()
{
if (gAgent.getRegion())
{
cap = gAgent.getRegion()->getCapability("LibraryAPIv3");
}
if (!cap.empty())
{
return true;
}
return false;
if (gAgent.getRegion())
{
return gAgent.getRegion()->getCapability(INVENTORY_CAP_NAME);
}
return std::string();
}
//static
void AISCommand::getCapabilityNames(LLSD& capabilityNames)
/*static*/
std::string AISAPI::getLibCap()
{
capabilityNames.append("InventoryAPIv3");
capabilityNames.append("LibraryAPIv3");
if (gAgent.getRegion())
{
return gAgent.getRegion()->getCapability(LIBRARY_CAP_NAME);
}
return std::string();
}
RemoveItemCommand::RemoveItemCommand(const LLUUID& item_id,
LLPointer<LLInventoryCallback> callback):
AISCommand(callback)
/*static*/
void AISAPI::CreateInventory(const LLUUID& parentId, const LLSD& newInventory, completion_t callback)
{
std::string cap;
if (!getInvCap(cap))
{
LL_WARNS() << "No cap found" << LL_ENDL;
return;
}
std::string url = cap + std::string("/item/") + item_id.asString();
std::string cap = getInvCap();
if (cap.empty())
{
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
return;
}
LLUUID tid;
tid.generate();
std::string url = cap + std::string("/category/") + parentId.asString() + "?tid=" + tid.asString();
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
LLHTTPClient::ResponderPtr responder = this;
command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off));
setCommandFunc(cmd);
boost::intrusive_ptr< AISCommand > responder = new AISCommand(COPYINVENTORY, "CreateInventory",parentId, callback);
responder->run(boost::bind(&LLHTTPClient::post, url, newInventory, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0));
}
RemoveCategoryCommand::RemoveCategoryCommand(const LLUUID& item_id,
LLPointer<LLInventoryCallback> callback):
AISCommand(callback)
/*static*/
void AISAPI::SlamFolder(const LLUUID& folderId, const LLSD& newInventory, completion_t callback)
{
std::string cap;
if (!getInvCap(cap))
{
LL_WARNS() << "No cap found" << LL_ENDL;
return;
}
std::string url = cap + std::string("/category/") + item_id.asString();
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
LLHTTPClient::ResponderPtr responder = this;
command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off));
setCommandFunc(cmd);
}
std::string cap = getInvCap();
if (cap.empty())
{
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
return;
}
PurgeDescendentsCommand::PurgeDescendentsCommand(const LLUUID& item_id,
LLPointer<LLInventoryCallback> callback):
AISCommand(callback)
{
std::string cap;
if (!getInvCap(cap))
{
LL_WARNS() << "No cap found" << LL_ENDL;
return;
}
std::string url = cap + std::string("/category/") + item_id.asString() + "/children";
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
LLHTTPClient::ResponderPtr responder = this;
command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off));
setCommandFunc(cmd);
}
LLUUID tid;
tid.generate();
std::string url = cap + std::string("/category/") + folderId.asString() + "/links?tid=" + tid.asString();
UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id,
const LLSD& updates,
LLPointer<LLInventoryCallback> callback):
mUpdates(updates),
AISCommand(callback)
{
std::string cap;
if (!getInvCap(cap))
{
LL_WARNS() << "No cap found" << LL_ENDL;
return;
}
std::string url = cap + std::string("/item/") + item_id.asString();
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
LL_DEBUGS("Inventory") << "request: " << ll_pretty_print_sd(mUpdates) << LL_ENDL;
LLHTTPClient::ResponderPtr responder = this;
AIHTTPHeaders headers;
headers.addHeader("Content-Type", "application/llsd+xml");
command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0);
setCommandFunc(cmd);
boost::intrusive_ptr< AISCommand > responder = new AISCommand(SLAMFOLDER, "SlamFolder", folderId, callback);
responder->run(boost::bind(&LLHTTPClient::put, url, newInventory, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug_off)));
}
UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& cat_id,
const LLSD& updates,
LLPointer<LLInventoryCallback> callback):
mUpdates(updates),
AISCommand(callback)
void AISAPI::RemoveCategory(const LLUUID &categoryId, completion_t callback)
{
std::string cap;
if (!getInvCap(cap))
{
LL_WARNS() << "No cap found" << LL_ENDL;
return;
}
std::string url = cap + std::string("/category/") + cat_id.asString();
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
LLHTTPClient::ResponderPtr responder = this;
AIHTTPHeaders headers;
headers.addHeader("Content-Type", "application/llsd+xml");
command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0);
setCommandFunc(cmd);
std::string cap;
cap = getInvCap();
if (cap.empty())
{
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
return;
}
std::string url = cap + std::string("/category/") + categoryId.asString();
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
boost::intrusive_ptr< AISCommand > responder = new AISCommand(REMOVECATEGORY, "RemoveCategory",categoryId, callback);
responder->run(boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)));
}
CreateInventoryCommand::CreateInventoryCommand(const LLUUID& parent_id,
const LLSD& new_inventory,
LLPointer<LLInventoryCallback> callback):
mNewInventory(new_inventory),
AISCommand(callback)
/*static*/
void AISAPI::RemoveItem(const LLUUID &itemId, completion_t callback)
{
std::string cap;
if (!getInvCap(cap))
{
LL_WARNS() << "No cap found" << LL_ENDL;
return;
}
LLUUID tid;
tid.generate();
std::string url = cap + std::string("/category/") + parent_id.asString() + "?tid=" + tid.asString();
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
LLHTTPClient::ResponderPtr responder = this;
AIHTTPHeaders headers;
headers.addHeader("Content-Type", "application/llsd+xml");
command_func_type cmd = boost::bind(&LLHTTPClient::post, url, mNewInventory, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0);
setCommandFunc(cmd);
std::string cap;
cap = getInvCap();
if (cap.empty())
{
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
return;
}
std::string url = cap + std::string("/item/") + itemId.asString();
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
boost::intrusive_ptr< AISCommand > responder = new AISCommand(REMOVEITEM,"RemoveItem",itemId, callback);
responder->run(boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)));
}
SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback):
mContents(contents),
AISCommand(callback)
void AISAPI::CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback)
{
std::string cap;
if (!getInvCap(cap))
{
LL_WARNS() << "No cap found" << LL_ENDL;
return;
}
LLUUID tid;
tid.generate();
std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString();
LL_INFOS() << url << LL_ENDL;
LLHTTPClient::ResponderPtr responder = this;
AIHTTPHeaders headers;
headers.addHeader("Content-Type", "application/llsd+xml");
command_func_type cmd = boost::bind(&LLHTTPClient::put, url, mContents, responder, headers/*,*/ DEBUG_CURLIO_PARAM(debug_off));
setCommandFunc(cmd);
std::string cap;
cap = getLibCap();
if (cap.empty())
{
LL_WARNS("Inventory") << "Library cap not found!" << LL_ENDL;
return;
}
LL_DEBUGS("Inventory") << "Copying library category: " << sourceId << " => " << destId << LL_ENDL;
LLUUID tid;
tid.generate();
std::string url = cap + std::string("/category/") + sourceId.asString() + "?tid=" + tid.asString();
if (!copySubfolders)
{
url += ",depth=0";
}
LL_INFOS() << url << LL_ENDL;
std::string destination = destId.asString();
boost::intrusive_ptr< AISCommand > responder = new AISCommand(COPYLIBRARYCATEGORY, "CopyLibraryCategory",destId, callback);
responder->run(boost::bind(&LLHTTPClient::copy, url, destination, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)));
}
CopyLibraryCategoryCommand::CopyLibraryCategoryCommand(const LLUUID& source_id,
const LLUUID& dest_id,
LLPointer<LLInventoryCallback> callback):
AISCommand(callback)
/*static*/
void AISAPI::PurgeDescendents(const LLUUID &categoryId, completion_t callback)
{
std::string cap;
if (!getLibCap(cap))
{
LL_WARNS() << "No cap found" << LL_ENDL;
return;
}
LL_DEBUGS("Inventory") << "Copying library category: " << source_id << " => " << dest_id << LL_ENDL;
LLUUID tid;
tid.generate();
std::string url = cap + std::string("/category/") + source_id.asString() + "?tid=" + tid.asString();
LL_INFOS() << url << LL_ENDL;
LLHTTPClient::ResponderPtr responder = this;
command_func_type cmd = boost::bind(&LLHTTPClient::copy, url, dest_id.asString(), responder);
setCommandFunc(cmd);
std::string cap;
cap = getInvCap();
if (cap.empty())
{
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
return;
}
std::string url = cap + std::string("/category/") + categoryId.asString() + "/children";
LL_DEBUGS("Inventory") << "url: " << url << LL_ENDL;
boost::intrusive_ptr< AISCommand > responder = new AISCommand(PURGEDESCENDENTS, "PurgeDescendents",categoryId, callback);
responder->run(boost::bind(&LLHTTPClient::del, url, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off)));
}
bool CopyLibraryCategoryCommand::getResponseUUID(const LLSD& content, LLUUID& id)
/*static*/
void AISAPI::UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback)
{
if (content.has("category_id"))
{
id = content["category_id"];
return true;
}
return false;
std::string cap;
cap = getInvCap();
if (cap.empty())
{
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
return;
}
std::string url = cap + std::string("/category/") + categoryId.asString();
boost::intrusive_ptr< AISCommand > responder = new AISCommand(UPDATECATEGORY, "UpdateCategory",categoryId, callback);
responder->run(boost::bind(&LLHTTPClient::patch, url, updates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0));
}
/*static*/
void AISAPI::UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback)
{
std::string cap;
cap = getInvCap();
if (cap.empty())
{
LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
return;
}
std::string url = cap + std::string("/item/") + itemId.asString();
boost::intrusive_ptr< AISCommand > responder = new AISCommand(UPDATEITEM, "UpdateItem",itemId, callback);
responder->run(boost::bind(&LLHTTPClient::patch, url, updates, responder/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, (AIStateMachine*)NULL, 0));
}
void AISAPI::InvokeAISCommandCoro(LLHTTPClient::ResponderWithResult* responder,
std::string url,
LLUUID targetId, LLSD result, completion_t callback, COMMAND_TYPE type)
{
{
if (!result.isMap())
{
responder->failureResult(400, "Malformed response contents", result);
return;
}
((AISCommand*)responder)->markComplete();
}
gInventory.onAISUpdateReceived("AISCommand", result);
if (callback && callback != nullptr)
{
LLUUID id(LLUUID::null);
if (result.has("category_id") && (type == COPYLIBRARYCATEGORY))
{
id = result["category_id"];
}
callback(id);
}
}
//-------------------------------------------------------------------------
AISUpdate::AISUpdate(const LLSD& update)
{
parseUpdate(update);
@@ -550,13 +559,25 @@ void AISUpdate::parseCategory(const LLSD& category_map)
parseDescendentCount(category_id, category_map["_embedded"]);
}
LLPointer<LLViewerInventoryCategory> new_cat(new LLViewerInventoryCategory(category_id));
LLPointer<LLViewerInventoryCategory> new_cat;
LLViewerInventoryCategory *curr_cat = gInventory.getCategory(category_id);
if (curr_cat)
{
// Default to current values where not provided.
new_cat->copyViewerCategory(curr_cat);
new_cat = new LLViewerInventoryCategory(curr_cat);
}
else
{
if (category_map.has("agent_id"))
{
new_cat = new LLViewerInventoryCategory(category_map["agent_id"].asUUID());
}
else
{
LL_DEBUGS() << "No owner provided, folder might be assigned wrong owner" << LL_ENDL;
new_cat = new LLViewerInventoryCategory(LLUUID::null);
}
}
BOOL rv = new_cat->unpackMessage(category_map);
// *NOTE: unpackMessage does not unpack version or descendent count.
//if (category_map.has("version"))
@@ -749,7 +770,7 @@ void AISUpdate::doUpdate()
for (std::map<LLUUID,S32>::const_iterator catit = mCatDescendentDeltas.begin();
catit != mCatDescendentDeltas.end(); ++catit)
{
LL_DEBUGS("Inventory") << "descendent accounting for " << catit->first << LL_ENDL;
LL_DEBUGS("Inventory") << "descendant accounting for " << catit->first << LL_ENDL;
const LLUUID cat_id(catit->first);
// Don't account for update if we just created this category.
@@ -772,7 +793,7 @@ void AISUpdate::doUpdate()
{
S32 descendent_delta = catit->second;
S32 old_count = cat->getDescendentCount();
LL_DEBUGS("Inventory") << "Updating descendent count for "
LL_DEBUGS("Inventory") << "Updating descendant count for "
<< cat->getName() << " " << cat_id
<< " with delta " << descendent_delta << " from "
<< old_count << " to " << (old_count+descendent_delta) << LL_ENDL;
@@ -850,7 +871,7 @@ void AISUpdate::doUpdate()
for (uuid_list_t::const_iterator del_it = mObjectsDeletedIds.begin();
del_it != mObjectsDeletedIds.end(); ++del_it)
{
LL_INFOS("Inventory") << "deleted item " << *del_it << LL_ENDL;
LL_DEBUGS("Inventory") << "deleted item " << *del_it << LL_ENDL;
gInventory.onObjectDeletedFromServer(*del_it, false, false, false);
}
@@ -868,7 +889,16 @@ void AISUpdate::doUpdate()
{
LL_WARNS() << "Possible version mismatch for category " << cat->getName()
<< ", viewer version " << cat->getVersion()
<< " server version " << version << LL_ENDL;
<< " AIS version " << version << " !!!Adjusting local version!!!" << LL_ENDL;
// the AIS version should be considered the true version. Adjust
// our local category model to reflect this version number. Otherwise
// it becomes possible to get stuck with the viewer being out of
// sync with the inventory system. Under normal circumstances
// inventory COF is maintained on the viewer through calls to
// LLInventoryModel::accountForUpdate when a changing operation
// is performed. This occasionally gets out of sync however.
cat->setVersion(version);
}
}

View File

@@ -36,118 +36,45 @@
#include "llhttpretrypolicy.h"
#include "llviewerinventory.h"
class AISCommand: public LLHTTPClient::ResponderWithResult
class AISAPI
{
friend class AISCommand;
public:
typedef boost::function<void()> command_func_type;
typedef std::function<void(const LLUUID &invItem)> completion_t;
AISCommand(LLPointer<LLInventoryCallback> callback);
static bool isAvailable();
static void getCapNames(LLSD& capNames);
virtual ~AISCommand() {}
static void CreateInventory(const LLUUID& parentId, const LLSD& newInventory, completion_t callback = completion_t());
static void SlamFolder(const LLUUID& folderId, const LLSD& newInventory, completion_t callback = completion_t());
static void RemoveCategory(const LLUUID &categoryId, completion_t callback = completion_t());
static void RemoveItem(const LLUUID &itemId, completion_t callback = completion_t());
static void PurgeDescendents(const LLUUID &categoryId, completion_t callback = completion_t());
static void UpdateCategory(const LLUUID &categoryId, const LLSD &updates, completion_t callback = completion_t());
static void UpdateItem(const LLUUID &itemId, const LLSD &updates, completion_t callback = completion_t());
static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t());
bool run_command();
private:
typedef enum {
COPYINVENTORY,
SLAMFOLDER,
REMOVECATEGORY,
REMOVEITEM,
PURGEDESCENDENTS,
UPDATECATEGORY,
UPDATEITEM,
COPYLIBRARYCATEGORY
} COMMAND_TYPE;
void setCommandFunc(command_func_type command_func);
static const std::string INVENTORY_CAP_NAME;
static const std::string LIBRARY_CAP_NAME;
// Need to do command-specific parsing to get an id here, for
// LLInventoryCallback::fire(). May or may not need to bother,
// since most LLInventoryCallbacks do their work in the
// destructor.
static std::string getInvCap();
static std::string getLibCap();
/* virtual */ void httpSuccess();
/* virtual */ void httpFailure();
static bool isAPIAvailable();
static bool getInvCap(std::string& cap);
static bool getLibCap(std::string& cap);
static void getCapabilityNames(LLSD& capabilityNames);
protected:
virtual bool getResponseUUID(const LLSD& content, LLUUID& id);
private:
command_func_type mCommandFunc;
LLPointer<LLHTTPRetryPolicy> mRetryPolicy;
LLPointer<LLInventoryCallback> mCallback;
};
class RemoveItemCommand: public AISCommand
{
public:
RemoveItemCommand(const LLUUID& item_id,
LLPointer<LLInventoryCallback> callback);
/* virtual */ const char* getName() const { return "RemoveItemCommand"; }
};
class RemoveCategoryCommand: public AISCommand
{
public:
RemoveCategoryCommand(const LLUUID& item_id,
LLPointer<LLInventoryCallback> callback);
/* virtual */ const char* getName() const { return "RemoveCategoryCommand"; }
};
class PurgeDescendentsCommand: public AISCommand
{
public:
PurgeDescendentsCommand(const LLUUID& item_id,
LLPointer<LLInventoryCallback> callback);
/* virtual */ const char* getName() const { return "PurgeDescendentsCommand"; }
};
class UpdateItemCommand: public AISCommand
{
public:
UpdateItemCommand(const LLUUID& item_id,
const LLSD& updates,
LLPointer<LLInventoryCallback> callback);
/* virtual */ const char* getName() const { return "UpdateItemCommand"; }
private:
LLSD mUpdates;
};
class UpdateCategoryCommand: public AISCommand
{
public:
UpdateCategoryCommand(const LLUUID& cat_id,
const LLSD& updates,
LLPointer<LLInventoryCallback> callback);
/* virtual */ const char* getName() const { return "UpdateCategoryCommand"; }
private:
LLSD mUpdates;
};
class SlamFolderCommand: public AISCommand
{
public:
SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback);
/* virtual */ const char* getName() const { return "SlamFolderCommand"; }
private:
LLSD mContents;
};
class CopyLibraryCategoryCommand: public AISCommand
{
public:
CopyLibraryCategoryCommand(const LLUUID& source_id, const LLUUID& dest_id, LLPointer<LLInventoryCallback> callback);
/* virtual */ const char* getName() const { return "CopyLibraryCategoryCommand"; }
protected:
/* virtual */ bool getResponseUUID(const LLSD& content, LLUUID& id);
};
class CreateInventoryCommand: public AISCommand
{
public:
CreateInventoryCommand(const LLUUID& parent_id, const LLSD& new_inventory, LLPointer<LLInventoryCallback> callback);
/* virtual */ const char* getName() const { return "CreateInventoryCommand"; }
private:
LLSD mNewInventory;
static void InvokeAISCommandCoro( LLHTTPClient::ResponderWithResult* responder,
std::string url, LLUUID targetId, LLSD body,
completion_t callback, COMMAND_TYPE type);
};
class AISUpdate

View File

@@ -60,6 +60,12 @@
#include "rlvlocks.h"
// [/RLVa:KB]
void doAppearanceCb(LLPointer<LLInventoryCallback> cb, LLUUID id)
{
if (cb.notNull())
cb->fire(id);
}
std::string self_av_string()
{
// On logout gAgentAvatarp can already be invalid
@@ -2842,8 +2848,7 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
<< " )" << LL_ENDL;
// If we are copying from library, attempt to use AIS to copy the category.
bool ais_ran=false;
if (copy && AISCommand::isAPIAvailable())
if (copy && AISAPI::isAvailable())
{
LLUUID parent_id;
parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
@@ -2855,11 +2860,11 @@ void LLAppearanceMgr::wearInventoryCategory(LLInventoryCategory* category, bool
LLPointer<LLInventoryCallback> copy_cb = new LLWearCategoryAfterCopy(append);
LLPointer<LLInventoryCallback> track_cb = new LLTrackPhaseWrapper(
std::string("wear_inventory_category_callback"), copy_cb);
boost::intrusive_ptr <AISCommand> cmd_ptr = new CopyLibraryCategoryCommand(category->getUUID(), parent_id, track_cb);
ais_ran=cmd_ptr->run_command();
}
if (!ais_ran)
AISAPI::completion_t cr = boost::bind(&doAppearanceCb, track_cb, _1);
AISAPI::CopyLibraryCategory(category->getUUID(), parent_id, false, cr);
}
else
{
selfStartPhase("wear_inventory_category_fetch");
callAfterCategoryFetch(category->getUUID(),boost::bind(&LLAppearanceMgr::wearCategoryFinal,
@@ -4123,7 +4128,7 @@ LLUUID LLAppearanceMgr::makeNewOutfitCore(const std::string& new_folder_name, bo
// First, make a folder in the My Outfits directory.
const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
if (AISCommand::isAPIAvailable())
if (AISAPI::isAvailable())
{
// cap-based category creation was buggy until recently. use
// existence of AIS as an indicator the fix is present. Does

View File

@@ -55,7 +55,7 @@
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be < MTUBYTES
// or 18 * count < 1200 => count < 1200/18 => 66. I've cut it down a
// bit from there to give some pad.
const S32 MAX_ITEMS = 42;
const size_t MAX_ITEMS = 42;
class LLGiveable : public LLInventoryCollectFunctor
{
@@ -259,9 +259,9 @@ bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
items,
LLInventoryModel::EXCLUDE_TRASH,
giveable);
S32 count = cats.size();
size_t count = cats.size();
bool complete = true;
for(S32 i = 0; i < count; ++i)
for(size_t i = 0; i < count; ++i)
{
if(!gInventory.isCategoryComplete(cats.at(i)->getUUID()))
{
@@ -475,8 +475,8 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons
items,
LLInventoryModel::EXCLUDE_TRASH,
remove);
S32 count = items.size();
for(S32 i = 0; i < count; ++i)
size_t count = items.size();
for(size_t i = 0; i < count; ++i)
{
gInventory.deleteObject(items.at(i)->getUUID());
}
@@ -529,8 +529,8 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be <
// MTUBYTES or 18 * count < 1200 => count < 1200/18 =>
// 66. I've cut it down a bit from there to give some pad.
S32 count = items.size() + cats.size();
if(count > MAX_ITEMS)
size_t count = items.size() + cats.size();
if (count > MAX_ITEMS)
{
LLNotificationsUtil::add("TooManyItems");
give_successful = false;
@@ -546,7 +546,7 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
LLAgentUI::buildFullname(name);
LLUUID transaction_id;
transaction_id.generate();
S32 bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1);
size_t bucket_size = (sizeof(U8) + UUID_BYTES) * (count + 1);
U8* bucket = new U8[bucket_size];
U8* pos = bucket;
U8 type = (U8)cat->getType();
@@ -554,7 +554,7 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
pos += sizeof(U8);
memcpy(pos, &(cat->getUUID()), UUID_BYTES); /* Flawfinder: ignore */
pos += UUID_BYTES;
S32 i;
size_t i;
count = cats.size();
for(i = 0; i < count; ++i)
{

View File

@@ -100,6 +100,8 @@
typedef std::pair<LLUUID, LLUUID> two_uuids_t;
typedef std::list<two_uuids_t> two_uuids_list_t;
const F32 SOUND_GAIN = 1.0f;
struct LLMoveInv
{
LLUUID mObjectID;
@@ -1829,13 +1831,15 @@ BOOL LLItemBridge::removeItem()
}
// move it to the trash
LLPreview::hide(mUUID, TRUE);
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
const LLUUID& trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
LLViewerInventoryItem* item = getItem();
if (!item) return FALSE;
if (item->getType() != LLAssetType::AT_LSL_TEXT)
{
LLPreview::hide(mUUID, TRUE);
}
// Already in trash
if (model->isObjectDescendentOf(mUUID, trash_id)) return FALSE;
@@ -4488,7 +4492,7 @@ void LLSoundBridge::previewItem()
LLViewerInventoryItem* item = getItem();
if(item)
{
send_sound_trigger(item->getAssetUUID(), 1.0);
send_sound_trigger(item->getAssetUUID(), SOUND_GAIN);
}
}
@@ -4554,7 +4558,7 @@ void LLSoundBridge::performAction(LLInventoryModel* model, std::string action)
LLViewerInventoryItem* item = getItem();
if(item)
{
send_sound_trigger(item->getAssetUUID(), 1.f);
send_sound_trigger(item->getAssetUUID(), SOUND_GAIN);
}
}
else if ("open" == action)

View File

@@ -83,6 +83,12 @@ static const char * const LOG_INV("Inventory");
static const char * const LOG_LOCAL("InventoryLocalize");
static const char * const LOG_NOTECARD("copy_inventory_from_notecard");
void doInventoryCb(LLPointer<LLInventoryCallback> cb, LLUUID id)
{
if (cb.notNull())
cb->fire(id);
}
///----------------------------------------------------------------------------
/// Helper class to store special inventory item names and their localized values.
///----------------------------------------------------------------------------
@@ -332,16 +338,42 @@ void LLViewerInventoryItem::updateServer(BOOL is_new) const
LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
gInventory.accountForUpdate(up);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_UpdateInventoryItem);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID);
msg->nextBlockFast(_PREHASH_InventoryData);
msg->addU32Fast(_PREHASH_CallbackID, 0);
packMessage(msg);
gAgent.sendReliableMessage();
if (AISAPI::isAvailable())
{
LLSD updates = asLLSD();
// Replace asset_id and/or shadow_id with transaction_id (hash_id)
if (updates.has("asset_id"))
{
updates.erase("asset_id");
if(getTransactionID().notNull())
{
updates["hash_id"] = getTransactionID();
}
}
if (updates.has("shadow_id"))
{
updates.erase("shadow_id");
if(getTransactionID().notNull())
{
updates["hash_id"] = getTransactionID();
}
}
AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>)NULL, _1);
AISAPI::UpdateItem(getUUID(), updates, cr);
}
else
{
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_UpdateInventoryItem);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->addUUIDFast(_PREHASH_TransactionID, mTransactionID);
msg->nextBlockFast(_PREHASH_InventoryData);
msg->addU32Fast(_PREHASH_CallbackID, 0);
packMessage(msg);
gAgent.sendReliableMessage();
}
}
void LLViewerInventoryItem::fetchFromServer(void) const
@@ -584,18 +616,26 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const
LLNotificationsUtil::add("CannotModifyProtectedCategories");
return;
}
if (AISAPI::isAvailable())
{
LLSD new_llsd = asLLSD();
AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>)NULL, _1);
AISAPI::UpdateCategory(getUUID(), new_llsd, cr);
}
else
{
LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
gInventory.accountForUpdate(up);
LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0);
gInventory.accountForUpdate(up);
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_FolderData);
packMessage(msg);
gAgent.sendReliableMessage();
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_FolderData);
packMessage(msg);
gAgent.sendReliableMessage();
}
}
S32 LLViewerInventoryCategory::getVersion() const
@@ -825,18 +865,33 @@ void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type)
const LLUUID &folder_id = getUUID();
const LLUUID &parent_id = getParentUUID();
const std::string &name = getName();
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_FolderData);
msg->addUUIDFast(_PREHASH_FolderID, folder_id);
msg->addUUIDFast(_PREHASH_ParentID, parent_id);
msg->addS8Fast(_PREHASH_Type, new_folder_type);
msg->addStringFast(_PREHASH_Name, name);
gAgent.sendReliableMessage();
if (AISAPI::isAvailable())
{
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(folder_id,
parent_id,
new_folder_type,
name,
gAgent.getID());
LLSD new_llsd = new_cat->asLLSD();
AISAPI::completion_t cr = boost::bind(&doInventoryCb, (LLPointer<LLInventoryCallback>) NULL, _1);
AISAPI::UpdateCategory(folder_id, new_llsd, cr);
}
else
{
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_FolderData);
msg->addUUIDFast(_PREHASH_FolderID, folder_id);
msg->addUUIDFast(_PREHASH_ParentID, parent_id);
msg->addS8Fast(_PREHASH_Type, new_folder_type);
msg->addStringFast(_PREHASH_Name, name);
gAgent.sendReliableMessage();
}
setPreferredType(new_folder_type);
gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id);
@@ -963,6 +1018,22 @@ void activate_gesture_cb(const LLUUID& inv_item)
LLGestureMgr::instance().activateGesture(inv_item);
}
void set_default_permissions(LLViewerInventoryItem* item, std::string perm_type)
{
llassert(item);
LLPermissions perm = item->getPermissions();
if (perm.getMaskEveryone() != LLFloaterPerms::getEveryonePerms(perm_type)
|| perm.getMaskGroup() != LLFloaterPerms::getGroupPerms(perm_type))
{
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms(perm_type));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms(perm_type));
item->setPermissions(perm);
item->updateServer(FALSE);
}
}
void create_script_cb(const LLUUID& inv_item)
{
if (!inv_item.isNull())
@@ -970,13 +1041,9 @@ void create_script_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
LLPermissions perm = item->getPermissions();
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Scripts"));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Scripts"));
set_default_permissions(item, "Scripts");
item->setPermissions(perm);
item->updateServer(FALSE);
// item was just created, update even if permissions did not changed
gInventory.updateItem(item);
gInventory.notifyObservers();
}
@@ -992,16 +1059,12 @@ void create_gesture_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
LLPermissions perm = item->getPermissions();
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Gestures"));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Gestures"));
set_default_permissions(item, "Gestures");
item->setPermissions(perm);
item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
if (!LLPreview::show(inv_item,FALSE))
{
LLPreviewGesture* preview = LLPreviewGesture::show(std::string("Gesture: ") + item->getName(), inv_item, LLUUID::null);
@@ -1019,13 +1082,8 @@ void create_notecard_cb(const LLUUID& inv_item)
LLViewerInventoryItem* item = gInventory.getItem(inv_item);
if (item)
{
LLPermissions perm = item->getPermissions();
perm.setMaskEveryone(LLFloaterPerms::getEveryonePerms("Notecards"));
perm.setMaskGroup(LLFloaterPerms::getGroupPerms("Notecards"));
set_default_permissions(item, "Notecards");
item->setPermissions(perm);
item->updateServer(FALSE);
gInventory.updateItem(item);
gInventory.notifyObservers();
}
@@ -1226,16 +1284,14 @@ void link_inventory_array(const LLUUID& category,
#endif
}
bool ais_ran = false;
if (AISCommand::isAPIAvailable())
if (AISAPI::isAvailable())
{
LLSD new_inventory = LLSD::emptyMap();
new_inventory["links"] = links;
boost::intrusive_ptr<AISCommand> cmd_ptr = new CreateInventoryCommand(category, new_inventory, cb);
ais_ran = cmd_ptr->run_command();
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
AISAPI::CreateInventory(category, new_inventory, cr);
}
if (!ais_ran)
else
{
LLMessageSystem* msg = gMessageSystem;
for (LLSD::array_iterator iter = links.beginArray(); iter != links.endArray(); ++iter )
@@ -1292,25 +1348,30 @@ void update_inventory_item(
LLPointer<LLInventoryCallback> cb)
{
const LLUUID& item_id = update_item->getUUID();
bool ais_ran = false;
if (AISCommand::isAPIAvailable())
if (AISAPI::isAvailable())
{
LLSD updates = update_item->asLLSD();
// Replace asset_id and/or shadow_id with transaction_id (hash_id)
if (updates.has("asset_id"))
{
updates.erase("asset_id");
updates["hash_id"] = update_item->getTransactionID();
if (update_item->getTransactionID().notNull())
{
updates["hash_id"] = update_item->getTransactionID();
}
}
if (updates.has("shadow_id"))
{
updates.erase("shadow_id");
updates["hash_id"] = update_item->getTransactionID();
if (update_item->getTransactionID().notNull())
{
updates["hash_id"] = update_item->getTransactionID();
}
}
boost::intrusive_ptr<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
ais_ran = cmd_ptr->run_command();
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
AISAPI::UpdateItem(item_id, updates, cr);
}
if (!ais_ran)
else
{
LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (update_item ? update_item->getName() : "(NOT FOUND)") << LL_ENDL;
@@ -1351,19 +1412,15 @@ void update_inventory_item(
// baking when using AISv3. Its omission looks likeley to be inconsequental, but if that's incorrect
// any bugs introduced by its removal are minor compared to non-functional serverside baking.
bool ais_ran = false;
if (AISCommand::isAPIAvailable())
if (AISAPI::isAvailable())
{
boost::intrusive_ptr<AISCommand> cmd_ptr = new UpdateItemCommand(item_id, updates, cb);
ais_ran = cmd_ptr->run_command();
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
AISAPI::UpdateItem(item_id, updates, cr);
}
if (!ais_ran)
else
{
LLPointer<LLViewerInventoryItem> obj = gInventory.getItem(item_id);
LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << (obj ? obj->getName() : "(NOT FOUND)") << LL_ENDL;
LLPointer<LLViewerInventoryItem> new_item = NULL;
if(obj)
{
LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem);
@@ -1410,12 +1467,11 @@ void update_inventory_category(
LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(obj);
new_cat->fromLLSD(updates);
// FIXME - restore this once the back-end work has been done.
if (AISCommand::isAPIAvailable())
if (AISAPI::isAvailable())
{
LLSD new_llsd = new_cat->asLLSD();
boost::intrusive_ptr<AISCommand> cmd_ptr = new UpdateCategoryCommand(cat_id, new_llsd, cb);
cmd_ptr->run_command();
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
AISAPI::UpdateCategory(cat_id, new_llsd, cr);
}
else // no cap
{
@@ -1477,10 +1533,10 @@ void remove_inventory_item(
{
const LLUUID item_id(obj->getUUID());
LL_DEBUGS(LOG_INV) << "item_id: [" << item_id << "] name " << obj->getName() << LL_ENDL;
if (AISCommand::isAPIAvailable())
if (AISAPI::isAvailable())
{
boost::intrusive_ptr<AISCommand> cmd_ptr = new RemoveItemCommand(item_id, cb);
cmd_ptr->run_command();
AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
AISAPI::RemoveItem(item_id, cr);
if (immediate_delete)
{
@@ -1553,10 +1609,10 @@ void remove_inventory_category(
LLNotificationsUtil::add("CannotRemoveProtectedCategories");
return;
}
if (AISCommand::isAPIAvailable())
if (AISAPI::isAvailable())
{
boost::intrusive_ptr<AISCommand> cmd_ptr = new RemoveCategoryCommand(cat_id, cb);
cmd_ptr->run_command();
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
AISAPI::RemoveCategory(cat_id, cr);
}
else // no cap
{
@@ -1656,10 +1712,10 @@ void purge_descendents_of(const LLUUID& id, LLPointer<LLInventoryCallback> cb)
}
else
{
if (AISCommand::isAPIAvailable())
if (AISAPI::isAvailable())
{
boost::intrusive_ptr<AISCommand> cmd_ptr = new PurgeDescendentsCommand(id, cb);
cmd_ptr->run_command();
AISAPI::completion_t cr = (cb) ? boost::bind(&doInventoryCb, cb, _1) : AISAPI::completion_t();
AISAPI::PurgeDescendents(id, cr);
}
else // no cap
{
@@ -1872,12 +1928,13 @@ void slam_inventory_folder(const LLUUID& folder_id,
const LLSD& contents,
LLPointer<LLInventoryCallback> cb)
{
if (AISCommand::isAPIAvailable())
if (AISAPI::isAvailable())
{
LL_DEBUGS(LOG_INV) << "using AISv3 to slam folder, id " << folder_id
<< " new contents: " << ll_pretty_print_sd(contents) << LL_ENDL;
boost::intrusive_ptr<AISCommand> cmd_ptr = new SlamFolderCommand(folder_id, contents, cb);
cmd_ptr->run_command();
AISAPI::completion_t cr = boost::bind(&doInventoryCb, cb, _1);
AISAPI::SlamFolder(folder_id, contents, cr);
}
else // no cap
{
@@ -2303,8 +2360,9 @@ LLUUID find_possible_item_for_regeneration(const LLViewerInventoryItem *target_i
item_iter != items.end();
++item_iter)
{
const LLViewerInventoryItem *item = (*item_iter);
if (true) return item->getUUID();
const LLViewerInventoryItem *item = (*item_iter);
if(item)
return item->getUUID();
}
return LLUUID::null;
}

View File

@@ -1905,7 +1905,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
capabilityNames.append("FetchInventoryDescendents2");
capabilityNames.append("IncrementCOFVersion");
capabilityNames.append("GamingData"); //Used by certain grids.
AISCommand::getCapabilityNames(capabilityNames);
AISAPI::getCapNames(capabilityNames);
capabilityNames.append("GetDisplayNames");
capabilityNames.append("GetMesh");
capabilityNames.append("GetMesh2"); // Used on SecondLife(tm) sim versions 280647 and higher (13.09.17).