diff options
author | Don Kjer <don@lindenlab.com> | 2012-12-06 22:56:21 +0000 |
---|---|---|
committer | Don Kjer <don@lindenlab.com> | 2012-12-06 22:56:21 +0000 |
commit | 23d77d3a34e48de6e9c69d60cdbd1d70766ad16c (patch) | |
tree | 84c2878deeb7ba8f4e408365ca53c3d119a15cb1 /indra | |
parent | 07d05c2967fb1013a3f21c1c055ad068b2be9995 (diff) | |
parent | 97adf6422ac61148a3334d67b4c59a5f5437af2c (diff) |
Automated merge
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) +{ +} |