diff options
| -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 | 
