diff options
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/cmake/Python.cmake | 2 | ||||
| -rw-r--r-- | indra/llcommon/tests/bitpack_test.cpp | 1 | ||||
| -rw-r--r-- | indra/llvfs/llvfile.cpp | 7 | ||||
| -rw-r--r-- | indra/llwindow/llwindowsdl.cpp | 3 | ||||
| -rwxr-xr-x | indra/newview/CMakeLists.txt | 9 | ||||
| -rwxr-xr-x | indra/newview/app_settings/settings.xml | 11 | ||||
| -rwxr-xr-x | indra/newview/llappearancemgr.cpp | 356 | ||||
| -rw-r--r-- | indra/newview/tests/llviewertexture_stub.cpp | 32 | 
8 files changed, 360 insertions, 61 deletions
| diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake index 748c8c2bec..a81c9307fc 100644 --- a/indra/cmake/Python.cmake +++ b/indra/cmake/Python.cmake @@ -23,7 +23,7 @@ if (WINDOWS)  elseif (EXISTS /etc/debian_version)    # On Debian and Ubuntu, avoid Python 2.4 if possible. -  find_program(PYTHON_EXECUTABLE python2.5 python2.3 python PATHS /usr/bin) +  find_program(PYTHON_EXECUTABLE python PATHS /usr/bin)    if (PYTHON_EXECUTABLE)      set(PYTHONINTERP_FOUND ON) diff --git a/indra/llcommon/tests/bitpack_test.cpp b/indra/llcommon/tests/bitpack_test.cpp index 7bca20c30a..afc0c18cd0 100644 --- a/indra/llcommon/tests/bitpack_test.cpp +++ b/indra/llcommon/tests/bitpack_test.cpp @@ -94,7 +94,6 @@ namespace tut  		ensure("bitPack: individual unpack: 5", unpackbuffer[0] == (U8) str[5]);  		bitunpack.bitUnpack(unpackbuffer, 8*4); // Life  		ensure_memory_matches("bitPack: 4 bytes unpack:", unpackbuffer, 4, str+6, 4); -		//ensure("keep compiler quiet", unpack_bufsize == unpack_bufsize);  	}  	// U32 packing diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp index ca749c5eaf..03d2cc25e3 100644 --- a/indra/llvfs/llvfile.cpp +++ b/indra/llvfs/llvfile.cpp @@ -32,6 +32,7 @@  #include "llthread.h"  #include "llstat.h"  #include "llvfs.h" +#include "llmemory.h"  const S32 LLVFile::READ			= 0x00000001;  const S32 LLVFile::WRITE		= 0x00000002; @@ -134,13 +135,13 @@ U8* LLVFile::readFile(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, S  		data = NULL;  	}  	else -	{ -		data = new U8[file_size]; +	{		 +		data = (U8*) ll_aligned_malloc_16(file_size);  		file.read(data, file_size);	/* Flawfinder: ignore */   		if (file.getLastBytesRead() != (S32)file_size)  		{ -			delete[] data; +			ll_aligned_free(data);  			data = NULL;  			file_size = 0;  		} diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index c7b141d7c1..9ea76df479 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -2645,8 +2645,9 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList()  	if (sortpat)  	{  		// Sort the list of system fonts from most-to-least-desirable. +		FcResult result;  		fs = FcFontSort(NULL, sortpat, elide_unicode_coverage, -				NULL, NULL); +				NULL, &result);  		FcPatternDestroy(sortpat);  	} diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index f85060a140..e64697982f 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2061,6 +2061,15 @@ if (LL_TESTS)    )    set_source_files_properties( +    llworldmap.cpp +    llworldmipmap.cpp +    PROPERTIES +    LL_TEST_ADDITIONAL_SOURCE_FILES  +    tests/llviewertexture_stub.cpp +    #llviewertexturelist.cpp +  ) + +  set_source_files_properties(      lltranslate.cpp      PROPERTIES      LL_TEST_ADDITIONAL_LIBRARIES "${JSONCPP_LIBRARIES}" diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index efb1ccc1cc..4a69e5b356 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4315,6 +4315,17 @@        <key>Value</key>        <real>1.0</real>      </map> +    <key>InventoryDebugSimulateOpFailureRate</key> +    <map> +      <key>Comment</key> +        <string>Rate at which we simulate failures of copy/link requests in some operations</string> +      <key>Persist</key> +        <integer>1</integer> +      <key>Type</key> +        <string>F32</string> +      <key>Value</key> +        <real>0.0</real> +    </map>      <key>InventoryDisplayInbox</key>      <map>          <key>Comment</key> diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 315811d709..98a8097a1e 100755 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -155,55 +155,298 @@ LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id, const std::string  	}  } -class LLWearInventoryCategoryCallback : public LLInventoryCallback +// Shim between inventory callback and boost function +typedef boost::function<void(const LLUUID&)> inventory_func_type; + +class LLBoostFuncInventoryCallback: public LLInventoryCallback  {  public: -	LLWearInventoryCategoryCallback(const LLUUID& cat_id, bool append) -	{ -		mCatID = cat_id; -		mAppend = append; -		LL_INFOS("Avatar") << self_av_string() << "starting" << LL_ENDL; -		 -		selfStartPhase("wear_inventory_category_callback"); +	LLBoostFuncInventoryCallback(const inventory_func_type& func): +		mFunc(func) +	{  	} +  	void fire(const LLUUID& item_id)  	{ -		/* -		 * Do nothing.  We only care about the destructor -		 * -		 * The reason for this is that this callback is used in a hack where the -		 * same callback is given to dozens of items, and the destructor is called -		 * after the last item has fired the event and dereferenced it -- if all -		 * the events actually fire! -		 */ -		LL_DEBUGS("Avatar") << self_av_string() << " fired on copied item, id " << item_id << LL_ENDL; +		mFunc(item_id);  	} -protected: -	~LLWearInventoryCategoryCallback() +private: +	inventory_func_type mFunc; +}; + +LLPointer<LLInventoryCallback> make_inventory_func_callback(const inventory_func_type& func) +{ +	return new LLBoostFuncInventoryCallback(func);  +} + +void report_fire(const LLUUID& item_id) +{ +	llinfos << item_id << llendl; +} + +void no_op() {} + +class LLCallAfterInventoryBatchMgr: public LLEventTimer  +{ +public: +	LLCallAfterInventoryBatchMgr(const LLUUID& dst_cat_id, +								 const std::string& phase_name, +								 nullary_func_t on_completion_func, +								 nullary_func_t on_failure_func = no_op, +								 F32 check_period = 5.0, +								 F32 retry_after = 10.0, +								 S32 max_retries = 2 +		): +		mDstCatID(dst_cat_id), +		mTrackingPhase(phase_name), +		mOnCompletionFunc(on_completion_func), +		mOnFailureFunc(on_failure_func), +		mRetryAfter(retry_after), +		mMaxRetries(max_retries), +		mPendingRequests(0), +		mFailCount(0), +		mCompletionOrFailureCalled(false), +		mRetryCount(0), +		LLEventTimer(check_period) +	{ +		if (!mTrackingPhase.empty()) +		{ +			selfStartPhase(mTrackingPhase); +		} +	} + +	void addItems(LLInventoryModel::item_array_t& src_items)  	{ -		LL_INFOS("Avatar") << self_av_string() << "done all inventory callbacks" << LL_ENDL; +		for (LLInventoryModel::item_array_t::const_iterator it = src_items.begin(); +			 it != src_items.end(); +			 ++it) +		{ +			LLViewerInventoryItem* item = *it; +			llassert(item); +			addItem(item); +		} +	} + +	// Request or re-request operation for specified item. +	void addItem(LLViewerInventoryItem *item) +	{ +		const LLUUID& item_id = item->getUUID(); +		if (!item) +		{ +			llwarns << "item not found for " << item_id << llendl; +			return; +		} +		mPendingRequests++; +		// On a re-request, this will reset the timer. +		mWaitTimes[item_id] = LLTimer(); +		if (mRetryCounts.find(item_id) == mRetryCounts.end()) +		{ +			mRetryCounts[item_id] = 0; +		} +		else +		{ +			mRetryCounts[item_id]++; +		} + +		if (ll_frand()<gSavedSettings.getF32("InventoryDebugSimulateOpFailureRate")) +		{ +			// simulate server failure by not sending the request. +			return; +		} -		selfStopPhase("wear_inventory_category_callback"); +		requestOperation(item); +	} + +	virtual void requestOperation(LLViewerInventoryItem *item) = 0; -		// Is the destructor called by ordinary dereference, or because the app's shutting down? -		// If the inventory callback manager goes away, we're shutting down, no longer want the callback. -		if( LLInventoryCallbackManager::is_instantiated() ) +	void onOp(const LLUUID& src_id, const LLUUID& dst_id) +	{ +		LL_DEBUGS("Avatar") << "op done, src_id " << src_id << " dst_id " << dst_id << " after " << mWaitTimes[src_id].getElapsedTimeF32() << " seconds" << llendl; +		mPendingRequests--; +		F32 wait_time = mWaitTimes[src_id].getElapsedTimeF32(); +		mTimeStats.push(wait_time); +		mWaitTimes.erase(src_id); +		if (mCompletionOrFailureCalled)  		{ -			LLAppearanceMgr::instance().wearInventoryCategoryOnAvatar(gInventory.getCategory(mCatID), mAppend); +			llinfos << "late-completing operation, src_id " << src_id << "dst_id " << dst_id << llendl; +		} +		if (mWaitTimes.empty() && !mCompletionOrFailureCalled) +		{ +			onCompletionOrFailure(); +		} +	} + +	void onCompletionOrFailure() +	{ +		assert (!mCompletionOrFailureCalled); +		mCompletionOrFailureCalled = true; +		 +		// Will never call onCompletion() if any item has been flagged as +		// a failure - otherwise could wind up with corrupted +		// outfit, involuntary nudity, etc. +		reportStats(); +		if (!mTrackingPhase.empty()) +		{ +			selfStopPhase(mTrackingPhase); +		} +		if (!mFailCount) +		{ +			onCompletion();  		}  		else  		{ -			llwarns << self_av_string() << "Dropping unhandled LLWearInventoryCategoryCallback" << llendl; +			onFailure();  		}  	} -private: -	LLUUID mCatID; -	bool mAppend; +	void onFailure() +	{ +		llinfos << "failed" << llendl; +		mOnFailureFunc(); +	} + +	void onCompletion() +	{ +		llinfos << "done" << llendl; +		mOnCompletionFunc(); +	} +	 +	// virtual +	// Will be deleted after returning true - only safe to do this if all callbacks have fired. +	BOOL tick() +	{ +		// mPendingRequests will be zero if all requests have been +		// responded to.  mWaitTimes.empty() will be true if we have +		// received at least one reply for each UUID.  If requests +		// have been dropped and retried, these will not necessarily +		// be the same.  Only safe to return true if all requests have +		// been serviced, since it will result in this object being +		// deleted. +		bool all_done = (mPendingRequests==0); + +		if (!mWaitTimes.empty()) +		{ +			llwarns << "still waiting on " << mWaitTimes.size() << " items" << llendl; +			for (std::map<LLUUID,LLTimer>::iterator it = mWaitTimes.begin(); +				 it != mWaitTimes.end();) +			{ +				// Use a copy of iterator because it may be erased/invalidated. +				std::map<LLUUID,LLTimer>::iterator curr_it = it; +				++it; +				 +				F32 time_waited = curr_it->second.getElapsedTimeF32(); +				S32 retries = mRetryCounts[curr_it->first]; +				if (time_waited > mRetryAfter) +				{ +					if (retries < mMaxRetries) +					{ +						LL_DEBUGS("Avatar") << "Waited " << time_waited << +							" for " << curr_it->first << ", retrying" << llendl; +						mRetryCount++; +						addItem(gInventory.getItem(curr_it->first)); +					} +					else +					{ +						llwarns << "Giving up on " << curr_it->first << " after too many retries" << llendl; +						mWaitTimes.erase(curr_it); +						mFailCount++; +					} +				} +				if (mWaitTimes.empty()) +				{ +					onCompletionOrFailure(); +				} + +			} +		} +		return all_done; +	} + +	void reportStats() +	{ +		LL_DEBUGS("Avatar") << "Phase: " << mTrackingPhase << llendl; +		LL_DEBUGS("Avatar") << "mFailCount: " << mFailCount << llendl; +		LL_DEBUGS("Avatar") << "mRetryCount: " << mRetryCount << llendl; +		LL_DEBUGS("Avatar") << "Times: n " << mTimeStats.getCount() << " min " << mTimeStats.getMinValue() << " max " << mTimeStats.getMaxValue() << llendl; +		LL_DEBUGS("Avatar") << "Mean " << mTimeStats.getMean() << " stddev " << mTimeStats.getStdDev() << llendl; +	} +	 +	virtual ~LLCallAfterInventoryBatchMgr() +	{ +		LL_DEBUGS("Avatar") << "deleting" << llendl; +	} + +protected: +	std::string mTrackingPhase; +	std::map<LLUUID,LLTimer> mWaitTimes; +	std::map<LLUUID,S32> mRetryCounts; +	LLUUID mDstCatID; +	nullary_func_t mOnCompletionFunc; +	nullary_func_t mOnFailureFunc; +	F32 mRetryAfter; +	S32 mMaxRetries; +	S32 mPendingRequests; +	S32 mFailCount; +	S32 mRetryCount; +	bool mCompletionOrFailureCalled; +	LLViewerStats::StatsAccumulator mTimeStats; +}; + +class LLCallAfterInventoryCopyMgr: public LLCallAfterInventoryBatchMgr +{ +public: +	LLCallAfterInventoryCopyMgr(LLInventoryModel::item_array_t& src_items, +								const LLUUID& dst_cat_id, +								const std::string& phase_name, +								nullary_func_t on_completion_func, +								nullary_func_t on_failure_func = no_op +		): +		LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func) +	{ +		addItems(src_items); +	} +	 +	virtual void requestOperation(LLViewerInventoryItem *item) +	{ +		copy_inventory_item( +			gAgent.getID(), +			item->getPermissions().getOwner(), +			item->getUUID(), +			mDstCatID, +			std::string(), +			make_inventory_func_callback(boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item->getUUID(),_1)) +			); +	}  }; +class LLCallAfterInventoryLinkMgr: public LLCallAfterInventoryBatchMgr +{ +public: +	LLCallAfterInventoryLinkMgr(LLInventoryModel::item_array_t& src_items, +								const LLUUID& dst_cat_id, +								const std::string& phase_name, +								nullary_func_t on_completion_func, +								nullary_func_t on_failure_func = no_op +		): +		LLCallAfterInventoryBatchMgr(dst_cat_id, phase_name, on_completion_func, on_failure_func) +	{ +		addItems(src_items); +	} +	 +	virtual void requestOperation(LLViewerInventoryItem *item) +	{ +		link_inventory_item(gAgent.getID(), +							item->getLinkedUUID(), +							mDstCatID, +							item->getName(), +							item->LLInventoryItem::getDescription(), +							LLAssetType::AT_LINK, +							make_inventory_func_callback( +								boost::bind(&LLCallAfterInventoryBatchMgr::onOp,this,item->getUUID(),_1))); +	} +};  //Inventory callback updating "dirty" state when destroyed  class LLUpdateDirtyState: public LLInventoryCallback @@ -1527,34 +1770,38 @@ void LLAppearanceMgr::updateCOF(const LLUUID& category, bool append)  	purgeCategory(cof, keep_outfit_links);  	gInventory.notifyObservers(); -	// Create links to new COF contents. -	LL_DEBUGS("Avatar") << self_av_string() << "creating LLUpdateAppearanceOnDestroy" << LL_ENDL; -	LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy(!append); -  #ifndef LL_RELEASE_FOR_DOWNLOAD  	LL_DEBUGS("Avatar") << self_av_string() << "Linking body items" << LL_ENDL;  #endif -	linkAll(cof, body_items, link_waiter); + +	// Create links to new COF contents. +	LL_DEBUGS("Avatar") << self_av_string() << "creating LLCallAfterInventoryLinkMgr" << LL_ENDL; +	bool update_base_outfit_ordering = !append; +	LLCallAfterInventoryLinkMgr *link_waiter = +		new LLCallAfterInventoryLinkMgr(body_items,cof,"update_appearance_on_destroy", +										boost::bind(&LLAppearanceMgr::updateAppearanceFromCOF, +													LLAppearanceMgr::getInstance(), +													update_base_outfit_ordering));  #ifndef LL_RELEASE_FOR_DOWNLOAD  	LL_DEBUGS("Avatar") << self_av_string() << "Linking wear items" << LL_ENDL;  #endif -	linkAll(cof, wear_items, link_waiter); +	link_waiter->addItems(wear_items);  #ifndef LL_RELEASE_FOR_DOWNLOAD  	LL_DEBUGS("Avatar") << self_av_string() << "Linking obj items" << LL_ENDL;  #endif -	linkAll(cof, obj_items, link_waiter); +	link_waiter->addItems(obj_items);  #ifndef LL_RELEASE_FOR_DOWNLOAD  	LL_DEBUGS("Avatar") << self_av_string() << "Linking gesture items" << LL_ENDL;  #endif -	linkAll(cof, gest_items, link_waiter); +	link_waiter->addItems(gest_items);  	// Add link to outfit if category is an outfit.   	if (!append)  	{ -		createBaseOutfitLink(category, link_waiter); +		createBaseOutfitLink(category, NULL);  	}  	LL_DEBUGS("Avatar") << self_av_string() << "waiting for LLUpdateAppearanceOnDestroy" << LL_ENDL;  } @@ -1980,22 +2227,15 @@ void LLAppearanceMgr::wearCategoryFinal(LLUUID& cat_id, bool copy_items, bool ap  			pid,  			LLFolderType::FT_NONE,  			name); -		LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(new_cat_id, append); -		it = items->begin(); -		for(; it < end; ++it) -		{ -			item = *it; -			if(item) -			{ -				copy_inventory_item( -					gAgent.getID(), -					item->getPermissions().getOwner(), -					item->getUUID(), -					new_cat_id, -					std::string(), -					cb); -			} -		} + +		// Create a CopyMgr that will copy items, manage its own destruction +		new LLCallAfterInventoryCopyMgr( +			*items, new_cat_id, std::string("wear_inventory_category_callback"), +			boost::bind(&LLAppearanceMgr::wearInventoryCategoryOnAvatar, +						LLAppearanceMgr::getInstance(), +						gInventory.getCategory(new_cat_id), +						append)); +  		// BAP fixes a lag in display of created dir.  		gInventory.notifyObservers();  	} @@ -2012,7 +2252,13 @@ void LLAppearanceMgr::wearInventoryCategoryOnAvatar( LLInventoryCategory* catego  	// Avoid unintentionally overwriting old wearables.  We have to do  	// this up front to avoid having to deal with the case of multiple  	// wearables being dirty. -	if(!category) return; +	if (!category) return; + +	if ( !LLInventoryCallbackManager::is_instantiated() ) +	{ +		// shutting down, ignore. +		return; +	}  	LL_INFOS("Avatar") << self_av_string() << "wearInventoryCategoryOnAvatar '" << category->getName()  			 << "'" << LL_ENDL; diff --git a/indra/newview/tests/llviewertexture_stub.cpp b/indra/newview/tests/llviewertexture_stub.cpp new file mode 100644 index 0000000000..90e76a8f83 --- /dev/null +++ b/indra/newview/tests/llviewertexture_stub.cpp @@ -0,0 +1,32 @@ +/**  + * @file llviewertexture_stub.cpp + * @brief  stub class to allow unit testing + * + * $LicenseInfo:firstyear=2012&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 "linden_common.h" +#include "../llviewertexture.h" + +void LLViewerTexture::setBoostLevel(int level) +{ +} | 
