diff options
author | Brad Payne (Vir Linden) <vir@lindenlab.com> | 2013-06-07 12:58:04 -0400 |
---|---|---|
committer | Brad Payne (Vir Linden) <vir@lindenlab.com> | 2013-06-07 12:58:04 -0400 |
commit | 89e3959cf393ce9eeb058304264d4f55f4fe9ca2 (patch) | |
tree | a5a96828ef79d33890fb5bd6efc485c17563580f /indra/newview | |
parent | 41694a902dc8cfebebb6e23691d41cb5627fa5a1 (diff) |
SH-4216 WIP - moved AISv3 commands and responders to llaisapi.* files
Diffstat (limited to 'indra/newview')
-rwxr-xr-x | indra/newview/CMakeLists.txt | 2 | ||||
-rwxr-xr-x | indra/newview/llaisapi.cpp | 481 | ||||
-rwxr-xr-x | indra/newview/llaisapi.h | 143 | ||||
-rwxr-xr-x | indra/newview/llinventorymodel.cpp | 248 | ||||
-rwxr-xr-x | indra/newview/llviewerinventory.cpp | 3 |
5 files changed, 630 insertions, 247 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4560951900..dc9370bd69 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -98,6 +98,7 @@ include_directories(SYSTEM set(viewer_SOURCE_FILES groupchatlistener.cpp llaccountingcostmanager.cpp + llaisapi.cpp llagent.cpp llagentaccess.cpp llagentcamera.cpp @@ -679,6 +680,7 @@ set(viewer_HEADER_FILES ViewerInstall.cmake groupchatlistener.h llaccountingcostmanager.h + llaisapi.h llagent.h llagentaccess.h llagentcamera.h diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp new file mode 100755 index 0000000000..6adf35efb8 --- /dev/null +++ b/indra/newview/llaisapi.cpp @@ -0,0 +1,481 @@ +/** + * @file llaisapi.cpp + * @brief classes and functions for interfacing with the v3+ ais inventory service. + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + * + */ + +#include "llviewerprecompiledheaders.h" +#include "llaisapi.h" + +#include "llagent.h" +#include "llcallbacklist.h" +#include "llinventorymodel.h" +#include "llsdutil.h" +#include "llviewerregion.h" + +///---------------------------------------------------------------------------- +/// Classes for AISv3 support. +///---------------------------------------------------------------------------- + +// AISCommand - base class for retry-able HTTP requests using the AISv3 cap. +AISCommand::AISCommand(LLPointer<LLInventoryCallback> callback): + mCallback(callback) +{ + mRetryPolicy = new LLAdaptiveRetryPolicy(1.0, 32.0, 2.0, 10); +} + +void AISCommand::run_command() +{ + mCommandFunc(); +} + +void AISCommand::setCommandFunc(command_func_type command_func) +{ + mCommandFunc = command_func; +} + +// 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()) + { + failureResult(HTTP_INTERNAL_ERROR, "Malformed response contents", content); + return; + } + mRetryPolicy->onSuccess(); + + gInventory.onAISUpdateReceived("AISCommand", content); + + if (mCallback) + { + LLUUID item_id; // will default to null if parse fails. + getResponseUUID(content,item_id); + mCallback->fire(item_id); + } +} + +/*virtual*/ +void AISCommand::httpFailure() +{ + const LLSD& content = getContent(); + S32 status = getStatus(); + const std::string& reason = getReason(); + const LLSD& headers = getResponseHeaders(); + if (!content.isMap()) + { + LL_DEBUGS("Inventory") << "Malformed response contents " << content + << " status " << status << " reason " << reason << llendl; + } + else + { + LL_DEBUGS("Inventory") << "failed with content: " << ll_pretty_print_sd(content) + << " status " << status << " reason " << reason << llendl; + } + mRetryPolicy->onFailure(status, headers); + F32 seconds_to_wait; + if (mRetryPolicy->shouldRetry(seconds_to_wait)) + { + doAfterInterval(boost::bind(&AISCommand::run_command,this),seconds_to_wait); + } + else + { + // Command func holds a reference to self, need to release it + // after a success or final failure. + setCommandFunc(no_op); + } +} + +//static +bool AISCommand::getCap(std::string& cap) +{ + if (gAgent.getRegion()) + { + cap = gAgent.getRegion()->getCapability("InventoryAPIv3"); + } + if (!cap.empty()) + { + return true; + } + return false; +} + +RemoveItemCommand::RemoveItemCommand(const LLUUID& item_id, + LLPointer<LLInventoryCallback> callback): + AISCommand(callback) +{ + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/item/") + item_id.asString(); + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLHTTPClient::ResponderPtr responder = this; + LLSD headers; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); + setCommandFunc(cmd); +} + +RemoveCategoryCommand::RemoveCategoryCommand(const LLUUID& item_id, + LLPointer<LLInventoryCallback> callback): + AISCommand(callback) +{ + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/category/") + item_id.asString(); + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLHTTPClient::ResponderPtr responder = this; + LLSD headers; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); + setCommandFunc(cmd); +} + +PurgeDescendentsCommand::PurgeDescendentsCommand(const LLUUID& item_id, + LLPointer<LLInventoryCallback> callback): + AISCommand(callback) +{ + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/category/") + item_id.asString() + "/children"; + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLCurl::ResponderPtr responder = this; + LLSD headers; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::del, url, responder, headers, timeout); + setCommandFunc(cmd); +} + +UpdateItemCommand::UpdateItemCommand(const LLUUID& item_id, + const LLSD& updates, + LLPointer<LLInventoryCallback> callback): + mUpdates(updates), + AISCommand(callback) +{ + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/item/") + item_id.asString(); + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLCurl::ResponderPtr responder = this; + LLSD headers; + headers["Content-Type"] = "application/llsd+xml"; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout); + setCommandFunc(cmd); +} + +UpdateCategoryCommand::UpdateCategoryCommand(const LLUUID& item_id, + const LLSD& updates, + LLPointer<LLInventoryCallback> callback): + mUpdates(updates), + AISCommand(callback) +{ + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + std::string url = cap + std::string("/category/") + item_id.asString(); + LL_DEBUGS("Inventory") << "url: " << url << llendl; + LLCurl::ResponderPtr responder = this; + LLSD headers; + headers["Content-Type"] = "application/llsd+xml"; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::patch, url, mUpdates, responder, headers, timeout); + setCommandFunc(cmd); +} + +SlamFolderCommand::SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback): + mContents(contents), + AISCommand(callback) +{ + std::string cap; + if (!getCap(cap)) + { + llwarns << "No cap found" << llendl; + return; + } + LLUUID tid; + tid.generate(); + std::string url = cap + std::string("/category/") + folder_id.asString() + "/links?tid=" + tid.asString(); + llinfos << url << llendl; + LLCurl::ResponderPtr responder = this; + LLSD headers; + headers["Content-Type"] = "application/llsd+xml"; + F32 timeout = HTTP_REQUEST_EXPIRY_SECS; + command_func_type cmd = boost::bind(&LLHTTPClient::put, url, mContents, responder, headers, timeout); + setCommandFunc(cmd); +} + +AISUpdate::AISUpdate(const LLSD& update) +{ + parseUpdate(update); +} + +void AISUpdate::parseUpdate(const LLSD& update) +{ + // parse _categories_removed -> mObjectsDeleted + uuid_vec_t cat_ids; + parseUUIDArray(update,"_categories_removed",cat_ids); + for (uuid_vec_t::const_iterator it = cat_ids.begin(); + it != cat_ids.end(); ++it) + { + LLViewerInventoryCategory *cat = gInventory.getCategory(*it); + mCatDeltas[cat->getParentUUID()]--; + mObjectsDeleted.insert(*it); + } + + // parse _categories_items_removed -> mObjectsDeleted + uuid_vec_t item_ids; + parseUUIDArray(update,"_category_items_removed",item_ids); + for (uuid_vec_t::const_iterator it = item_ids.begin(); + it != item_ids.end(); ++it) + { + LLViewerInventoryItem *item = gInventory.getItem(*it); + mCatDeltas[item->getParentUUID()]--; + mObjectsDeleted.insert(*it); + } + + // parse _broken_links_removed -> mObjectsDeleted + uuid_vec_t broken_link_ids; + parseUUIDArray(update,"_broken_links_removed",broken_link_ids); + for (uuid_vec_t::const_iterator it = broken_link_ids.begin(); + it != broken_link_ids.end(); ++it) + { + LLViewerInventoryItem *item = gInventory.getItem(*it); + mCatDeltas[item->getParentUUID()]--; + mObjectsDeleted.insert(*it); + } + + // parse _created_items + parseUUIDArray(update,"_created_items",mItemsCreatedIds); + + if (update.has("_embedded")) + { + const LLSD& embedded = update["_embedded"]; + for(LLSD::map_const_iterator it = embedded.beginMap(), + end = embedded.endMap(); + it != end; ++it) + { + const std::string& field = (*it).first; + + // parse created links + if (field == "link") + { + const LLSD& links = embedded["link"]; + parseCreatedLinks(links); + } + else + { + llwarns << "unrecognized embedded field " << field << llendl; + } + } + + } + + // Parse item update at the top level. + if (update.has("item_id")) + { + LLUUID item_id = update["item_id"].asUUID(); + LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem); + BOOL rv = new_item->unpackMessage(update); + if (rv) + { + mItemsUpdated[item_id] = new_item; + // This statement is here to cause a new entry with 0 + // delta to be created if it does not already exist; + // otherwise has no effect. + mCatDeltas[new_item->getParentUUID()]; + } + else + { + llerrs << "unpack failed" << llendl; + } + } + + // Parse updated category versions. + const std::string& ucv = "_updated_category_versions"; + if (update.has(ucv)) + { + for(LLSD::map_const_iterator it = update[ucv].beginMap(), + end = update[ucv].endMap(); + it != end; ++it) + { + const LLUUID id((*it).first); + S32 version = (*it).second.asInteger(); + mCatVersions[id] = version; + } + } +} + +void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids) +{ + ids.clear(); + if (content.has(name)) + { + for(LLSD::array_const_iterator it = content[name].beginArray(), + end = content[name].endArray(); + it != end; ++it) + { + ids.push_back((*it).asUUID()); + } + } +} + +void AISUpdate::parseLink(const LLUUID& link_id, const LLSD& link_map) +{ + LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem); + BOOL rv = new_link->unpackMessage(link_map); + if (rv) + { + LLPermissions default_perms; + default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null); + default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE); + new_link->setPermissions(default_perms); + LLSaleInfo default_sale_info; + new_link->setSaleInfo(default_sale_info); + //LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl; + mItemsCreated[link_id] = new_link; + const LLUUID& parent_id = new_link->getParentUUID(); + mCatDeltas[parent_id]++; + } + else + { + llwarns << "failed to parse" << llendl; + } +} + +void AISUpdate::parseCreatedLinks(const LLSD& links) +{ + for(LLSD::map_const_iterator linkit = links.beginMap(), + linkend = links.endMap(); + linkit != linkend; ++linkit) + { + const LLUUID link_id((*linkit).first); + const LLSD& link_map = (*linkit).second; + uuid_vec_t::const_iterator pos = + std::find(mItemsCreatedIds.begin(), + mItemsCreatedIds.end(),link_id); + if (pos != mItemsCreatedIds.end()) + { + parseLink(link_id,link_map); + } + else + { + LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl; + } + } +} + +void AISUpdate::doUpdate() +{ + // Do descendent/version accounting. + // Can remove this if/when we use the version info directly. + for (std::map<LLUUID,S32>::const_iterator catit = mCatDeltas.begin(); + catit != mCatDeltas.end(); ++catit) + { + const LLUUID cat_id(catit->first); + S32 delta = catit->second; + LLInventoryModel::LLCategoryUpdate up(cat_id, delta); + gInventory.accountForUpdate(up); + } + + // TODO - how can we use this version info? Need to be sure all + // changes are going through AIS first, or at least through + // something with a reliable responder. + for (uuid_int_map_t::iterator ucv_it = mCatVersions.begin(); + ucv_it != mCatVersions.end(); ++ucv_it) + { + const LLUUID id = ucv_it->first; + S32 version = ucv_it->second; + LLViewerInventoryCategory *cat = gInventory.getCategory(id); + if (cat->getVersion() != version) + { + llwarns << "Possible version mismatch, viewer " << cat->getVersion() + << " server " << version << llendl; + } + } + + // CREATE ITEMS + for (deferred_item_map_t::const_iterator create_it = mItemsCreated.begin(); + create_it != mItemsCreated.end(); ++create_it) + { + LLUUID item_id(create_it->first); + LLPointer<LLViewerInventoryItem> new_item = create_it->second; + + // FIXME risky function since it calls updateServer() in some + // cases. Maybe break out the update/create cases, in which + // case this is create. + LL_DEBUGS("Inventory") << "created item " << item_id << llendl; + gInventory.updateItem(new_item); + } + + // UPDATE ITEMS + for (deferred_item_map_t::const_iterator update_it = mItemsUpdated.begin(); + update_it != mItemsUpdated.end(); ++update_it) + { + LLUUID item_id(update_it->first); + LLPointer<LLViewerInventoryItem> new_item = update_it->second; + // FIXME risky function since it calls updateServer() in some + // cases. Maybe break out the update/create cases, in which + // case this is update. + LL_DEBUGS("Inventory") << "updated item " << item_id << llendl; + gInventory.updateItem(new_item); + } + + // DELETE OBJECTS + for (std::set<LLUUID>::const_iterator del_it = mObjectsDeleted.begin(); + del_it != mObjectsDeleted.end(); ++del_it) + { + LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl; + gInventory.onObjectDeletedFromServer(*del_it, false, false); + } +} + diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h new file mode 100755 index 0000000000..1f9555f004 --- /dev/null +++ b/indra/newview/llaisapi.h @@ -0,0 +1,143 @@ +/** + * @file llaisapi.h + * @brief classes and functions for interfacing with the v3+ ais inventory service. + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLAISAPI_H +#define LL_LLAISAPI_H + +#include "lluuid.h" +#include <map> +#include <set> +#include <string> +#include <vector> +#include "llcurl.h" +#include "llhttpclient.h" +#include "llhttpretrypolicy.h" +#include "llviewerinventory.h" + +class AISCommand: public LLHTTPClient::Responder +{ +public: + typedef boost::function<void()> command_func_type; + + AISCommand(LLPointer<LLInventoryCallback> callback); + + virtual ~AISCommand() {} + + void run_command(); + + void setCommandFunc(command_func_type command_func); + + // 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. + virtual bool getResponseUUID(const LLSD& content, LLUUID& id); + + /* virtual */ void httpSuccess(); + + /*virtual*/ void httpFailure(); + + static bool getCap(std::string& cap); + +private: + command_func_type mCommandFunc; + LLPointer<LLHTTPRetryPolicy> mRetryPolicy; + LLPointer<LLInventoryCallback> mCallback; +}; + +class RemoveItemCommand: public AISCommand +{ +public: + RemoveItemCommand(const LLUUID& item_id, + LLPointer<LLInventoryCallback> callback); +}; + +class RemoveCategoryCommand: public AISCommand +{ +public: + RemoveCategoryCommand(const LLUUID& item_id, + LLPointer<LLInventoryCallback> callback); +}; + +class PurgeDescendentsCommand: public AISCommand +{ +public: + PurgeDescendentsCommand(const LLUUID& item_id, + LLPointer<LLInventoryCallback> callback); +}; + +class UpdateItemCommand: public AISCommand +{ +public: + UpdateItemCommand(const LLUUID& item_id, + const LLSD& updates, + LLPointer<LLInventoryCallback> callback); +private: + LLSD mUpdates; +}; + +class UpdateCategoryCommand: public AISCommand +{ +public: + UpdateCategoryCommand(const LLUUID& item_id, + const LLSD& updates, + LLPointer<LLInventoryCallback> callback); +private: + LLSD mUpdates; +}; + +class SlamFolderCommand: public AISCommand +{ +public: + SlamFolderCommand(const LLUUID& folder_id, const LLSD& contents, LLPointer<LLInventoryCallback> callback); + +private: + LLSD mContents; +}; + +class AISUpdate +{ +public: + AISUpdate(const LLSD& update); + void parseUpdate(const LLSD& update); + void parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids); + void parseLink(const LLUUID& link_id, const LLSD& link_map); + void parseCreatedLinks(const LLSD& links); + void doUpdate(); +private: + typedef std::map<LLUUID,S32> uuid_int_map_t; + uuid_int_map_t mCatDeltas; + uuid_int_map_t mCatVersions; + + typedef std::map<LLUUID,LLPointer<LLViewerInventoryItem> > deferred_item_map_t; + deferred_item_map_t mItemsCreated; + deferred_item_map_t mItemsUpdated; + + std::set<LLUUID> mObjectsDeleted; + uuid_vec_t mItemsCreatedIds; +}; + +#endif diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 3c7539a7f9..6dc193292e 100755 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llinventorymodel.h" +#include "llaisapi.h" #include "llagent.h" #include "llagentwearables.h" #include "llappearancemgr.h" @@ -1154,253 +1155,6 @@ void LLInventoryModel::changeCategoryParent(LLViewerInventoryCategory* cat, notifyObservers(); } -class AISUpdate -{ -public: - AISUpdate(const LLSD& update); - void parseUpdate(const LLSD& update); - void parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids); - void parseLink(const LLUUID& link_id, const LLSD& link_map); - void parseCreatedLinks(const LLSD& links); - void doUpdate(); -private: - typedef std::map<LLUUID,S32> uuid_int_map_t; - uuid_int_map_t mCatDeltas; - uuid_int_map_t mCatVersions; - - typedef std::map<LLUUID,LLPointer<LLViewerInventoryItem> > deferred_item_map_t; - deferred_item_map_t mItemsCreated; - deferred_item_map_t mItemsUpdated; - - std::set<LLUUID> mObjectsDeleted; - uuid_vec_t mItemsCreatedIds; -}; - -AISUpdate::AISUpdate(const LLSD& update) -{ - parseUpdate(update); -} - -void AISUpdate::parseUpdate(const LLSD& update) -{ - // parse _categories_removed -> mObjectsDeleted - uuid_vec_t cat_ids; - parseUUIDArray(update,"_categories_removed",cat_ids); - for (uuid_vec_t::const_iterator it = cat_ids.begin(); - it != cat_ids.end(); ++it) - { - LLViewerInventoryCategory *cat = gInventory.getCategory(*it); - mCatDeltas[cat->getParentUUID()]--; - mObjectsDeleted.insert(*it); - } - - // parse _categories_items_removed -> mObjectsDeleted - uuid_vec_t item_ids; - parseUUIDArray(update,"_category_items_removed",item_ids); - for (uuid_vec_t::const_iterator it = item_ids.begin(); - it != item_ids.end(); ++it) - { - LLViewerInventoryItem *item = gInventory.getItem(*it); - mCatDeltas[item->getParentUUID()]--; - mObjectsDeleted.insert(*it); - } - - // parse _broken_links_removed -> mObjectsDeleted - uuid_vec_t broken_link_ids; - parseUUIDArray(update,"_broken_links_removed",broken_link_ids); - for (uuid_vec_t::const_iterator it = broken_link_ids.begin(); - it != broken_link_ids.end(); ++it) - { - LLViewerInventoryItem *item = gInventory.getItem(*it); - mCatDeltas[item->getParentUUID()]--; - mObjectsDeleted.insert(*it); - } - - // parse _created_items - parseUUIDArray(update,"_created_items",mItemsCreatedIds); - - if (update.has("_embedded")) - { - const LLSD& embedded = update["_embedded"]; - for(LLSD::map_const_iterator it = embedded.beginMap(), - end = embedded.endMap(); - it != end; ++it) - { - const std::string& field = (*it).first; - - // parse created links - if (field == "link") - { - const LLSD& links = embedded["link"]; - parseCreatedLinks(links); - } - else - { - llwarns << "unrecognized embedded field " << field << llendl; - } - } - - } - - // Parse item update at the top level. - if (update.has("item_id")) - { - LLUUID item_id = update["item_id"].asUUID(); - LLPointer<LLViewerInventoryItem> new_item(new LLViewerInventoryItem); - BOOL rv = new_item->unpackMessage(update); - if (rv) - { - mItemsUpdated[item_id] = new_item; - // This statement is here to cause a new entry with 0 - // delta to be created if it does not already exist; - // otherwise has no effect. - mCatDeltas[new_item->getParentUUID()]; - } - else - { - llerrs << "unpack failed" << llendl; - } - } - - // Parse updated category versions. - const std::string& ucv = "_updated_category_versions"; - if (update.has(ucv)) - { - for(LLSD::map_const_iterator it = update[ucv].beginMap(), - end = update[ucv].endMap(); - it != end; ++it) - { - const LLUUID id((*it).first); - S32 version = (*it).second.asInteger(); - mCatVersions[id] = version; - } - } -} - -void AISUpdate::parseUUIDArray(const LLSD& content, const std::string& name, uuid_vec_t& ids) -{ - ids.clear(); - if (content.has(name)) - { - for(LLSD::array_const_iterator it = content[name].beginArray(), - end = content[name].endArray(); - it != end; ++it) - { - ids.push_back((*it).asUUID()); - } - } -} - -void AISUpdate::parseLink(const LLUUID& link_id, const LLSD& link_map) -{ - LLPointer<LLViewerInventoryItem> new_link(new LLViewerInventoryItem); - BOOL rv = new_link->unpackMessage(link_map); - if (rv) - { - LLPermissions default_perms; - default_perms.init(gAgent.getID(),gAgent.getID(),LLUUID::null,LLUUID::null); - default_perms.initMasks(PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE,PERM_NONE); - new_link->setPermissions(default_perms); - LLSaleInfo default_sale_info; - new_link->setSaleInfo(default_sale_info); - //LL_DEBUGS("Inventory") << "creating link from llsd: " << ll_pretty_print_sd(link_map) << llendl; - mItemsCreated[link_id] = new_link; - const LLUUID& parent_id = new_link->getParentUUID(); - mCatDeltas[parent_id]++; - } - else - { - llwarns << "failed to parse" << llendl; - } -} - -void AISUpdate::parseCreatedLinks(const LLSD& links) -{ - for(LLSD::map_const_iterator linkit = links.beginMap(), - linkend = links.endMap(); - linkit != linkend; ++linkit) - { - const LLUUID link_id((*linkit).first); - const LLSD& link_map = (*linkit).second; - uuid_vec_t::const_iterator pos = - std::find(mItemsCreatedIds.begin(), - mItemsCreatedIds.end(),link_id); - if (pos != mItemsCreatedIds.end()) - { - parseLink(link_id,link_map); - } - else - { - LL_DEBUGS("Inventory") << "Ignoring link not in created items list " << link_id << llendl; - } - } -} - -void AISUpdate::doUpdate() -{ - // Do descendent/version accounting. - // Can remove this if/when we use the version info directly. - for (std::map<LLUUID,S32>::const_iterator catit = mCatDeltas.begin(); - catit != mCatDeltas.end(); ++catit) - { - const LLUUID cat_id(catit->first); - S32 delta = catit->second; - LLInventoryModel::LLCategoryUpdate up(cat_id, delta); - gInventory.accountForUpdate(up); - } - - // TODO - how can we use this version info? Need to be sure all - // changes are going through AIS first, or at least through - // something with a reliable responder. - for (uuid_int_map_t::iterator ucv_it = mCatVersions.begin(); - ucv_it != mCatVersions.end(); ++ucv_it) - { - const LLUUID id = ucv_it->first; - S32 version = ucv_it->second; - LLViewerInventoryCategory *cat = gInventory.getCategory(id); - if (cat->getVersion() != version) - { - llwarns << "Possible version mismatch, viewer " << cat->getVersion() - << " server " << version << llendl; - } - } - - // CREATE ITEMS - for (deferred_item_map_t::const_iterator create_it = mItemsCreated.begin(); - create_it != mItemsCreated.end(); ++create_it) - { - LLUUID item_id(create_it->first); - LLPointer<LLViewerInventoryItem> new_item = create_it->second; - - // FIXME risky function since it calls updateServer() in some - // cases. Maybe break out the update/create cases, in which - // case this is create. - LL_DEBUGS("Inventory") << "created item " << item_id << llendl; - gInventory.updateItem(new_item); - } - - // UPDATE ITEMS - for (deferred_item_map_t::const_iterator update_it = mItemsUpdated.begin(); - update_it != mItemsUpdated.end(); ++update_it) - { - LLUUID item_id(update_it->first); - LLPointer<LLViewerInventoryItem> new_item = update_it->second; - // FIXME risky function since it calls updateServer() in some - // cases. Maybe break out the update/create cases, in which - // case this is update. - LL_DEBUGS("Inventory") << "updated item " << item_id << llendl; - gInventory.updateItem(new_item); - } - - // DELETE OBJECTS - for (std::set<LLUUID>::const_iterator del_it = mObjectsDeleted.begin(); - del_it != mObjectsDeleted.end(); ++del_it) - { - LL_DEBUGS("Inventory") << "deleted item " << *del_it << llendl; - gInventory.onObjectDeletedFromServer(*del_it, false, false); - } -} - void LLInventoryModel::onAISUpdateReceived(const std::string& context, const LLSD& update) { if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 0608c46051..57d7d4fef6 100755 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -31,6 +31,7 @@ #include "llsdserialize.h" #include "message.h" +#include "llaisapi.h" #include "llagent.h" #include "llagentcamera.h" #include "llagentwearables.h" @@ -258,6 +259,7 @@ public: }; LLInventoryHandler gInventoryHandler; +#if 0 // DELETE these when working in their new home ///---------------------------------------------------------------------------- /// Classes for AISv3 support. @@ -520,6 +522,7 @@ public: private: LLSD mContents; }; +#endif ///---------------------------------------------------------------------------- /// Class LLViewerInventoryItem |