diff --git a/indra/aistatemachine/aistatemachine.h b/indra/aistatemachine/aistatemachine.h index 160c6d6eb..9b5b0aab6 100644 --- a/indra/aistatemachine/aistatemachine.h +++ b/indra/aistatemachine/aistatemachine.h @@ -146,12 +146,15 @@ class AIStateMachine : public LLThreadSafeRefCount typedef AIAccessConst multiplex_state_type_crat; typedef AIAccess multiplex_state_type_rat; typedef AIAccess multiplex_state_type_wat; + + protected: // Sub state. AIThreadSafeSimpleDC mSubState; typedef AIAccessConst sub_state_type_crat; typedef AIAccess sub_state_type_rat; typedef AIAccess sub_state_type_wat; + private: // Mutex protecting everything below and making sure only one thread runs the state machine at a time. LLMutex mMultiplexMutex; // Mutex that is locked while calling *_impl() functions and the call back. diff --git a/indra/llcommon/aithreadid.h b/indra/llcommon/aithreadid.h index cc7197b21..6b2c08516 100644 --- a/indra/llcommon/aithreadid.h +++ b/indra/llcommon/aithreadid.h @@ -33,7 +33,7 @@ #include // apr_os_thread_t, apr_os_thread_current(), apr_os_thread_equal(). #include // std::ostream. -#include "llpreprocessor.h" // LL_COMMON_API, LL_COMMON_API_TLS +#include "llpreprocessor.h" // LL_COMMON_API, LL_COMMON_API_TLS, LL_UNLIKELY // Lightweight wrapper around apr_os_thread_t. // This class introduces no extra assembly code after optimization; it's only intend is to provide type-safety. @@ -87,6 +87,16 @@ public: #endif }; +// Debugging function. +inline bool is_single_threaded(AIThreadID& thread_id) +{ + if (LL_UNLIKELY(thread_id.is_no_thread())) + { + thread_id.reset(); + } + return thread_id.equals_current_thread(); +} + // Legacy function. inline bool is_main_thread(void) { diff --git a/indra/llmessage/aicurlperservice.cpp b/indra/llmessage/aicurlperservice.cpp index 9e13f98c7..28721c1e9 100644 --- a/indra/llmessage/aicurlperservice.cpp +++ b/indra/llmessage/aicurlperservice.cpp @@ -81,6 +81,15 @@ AIPerService::AIPerService(void) : { } +AIPerService::~AIPerService() +{ +} + +// Fake copy constructor. +AIPerService::AIPerService(AIPerService const&) : mHTTPBandwidth(0) +{ +} + // url must be of the form // (see http://www.ietf.org/rfc/rfc3986.txt Appendix A for definitions not given here): // diff --git a/indra/llmessage/aicurlperservice.h b/indra/llmessage/aicurlperservice.h index a64d0d57f..20271aeb3 100644 --- a/indra/llmessage/aicurlperservice.h +++ b/indra/llmessage/aicurlperservice.h @@ -92,6 +92,9 @@ class AIPerService { friend class AIThreadSafeSimpleDC; //threadsafe_PerServiceRequestQueue AIPerService(void); + public: + ~AIPerService(); + public: typedef instance_map_type::iterator iterator; typedef instance_map_type::const_iterator const_iterator; @@ -159,7 +162,7 @@ class AIPerService { private: // Disallow copying. - AIPerService(AIPerService const&) : mHTTPBandwidth(0) { } + AIPerService(AIPerService const&); }; namespace AICurlPrivate { diff --git a/indra/llmessage/aicurlprivate.h b/indra/llmessage/aicurlprivate.h index abdc978d4..57e6d9210 100644 --- a/indra/llmessage/aicurlprivate.h +++ b/indra/llmessage/aicurlprivate.h @@ -305,7 +305,7 @@ class CurlEasyRequest : public CurlEasyHandle { AIHTTPTimeoutPolicy const* mTimeoutPolicy; std::string mLowercaseServicename; // Lowercase hostname:port (canonicalized) extracted from the url. - AIPerServicePtr mPerServicePtr; // Pointer to the corresponding AIPerService. + AIPerServicePtr mPerServicePtr; // Pointer to the corresponding AIPerService. LLPointer mTimeout;// Timeout administration object associated with last created CurlSocketInfo. bool mTimeoutIsOrphan; // Set to true when mTimeout is not (yet) associated with a CurlSocketInfo. #if defined(CWDEBUG) || defined(DEBUG_CURLIO) diff --git a/indra/llmessage/aicurlthread.cpp b/indra/llmessage/aicurlthread.cpp index 47a4d6d59..8b4f1a022 100644 --- a/indra/llmessage/aicurlthread.cpp +++ b/indra/llmessage/aicurlthread.cpp @@ -2624,7 +2624,7 @@ bool AIPerService::wantsMoreHTTPRequestsFor(AIPerServicePtr const& per_service, } } - // Check if it's ok to get a new request for this particular host and update the per-host threshold. + // Check if it's ok to get a new request for this particular service and update the per-service threshold. AIAverage* http_bandwidth_ptr; diff --git a/indra/newview/linux_tools/refresh_desktop_app_entry.sh b/indra/newview/linux_tools/refresh_desktop_app_entry.sh old mode 100644 new mode 100755 diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index ff7fc48ae..0806df29d 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -141,7 +141,7 @@ if [ -n "$LL_TCMALLOC" ]; then fi export VIEWER_BINARY='singularity-do-not-run-directly' -BINARY_TYPE=$(expr match "$(file -b bin/$VIEWER_BINARY)" '\(.*executable\)') +BINARY_TYPE=$(expr match "$(file -b bin/$VIEWER_BINARY)" '\(.*executable\)' | sed -e 's/ / /g') if [ "${BINARY_TYPE}" == "ELF 64-bit LSB executable" ]; then SL_ENV+='LD_LIBRARY_PATH="`pwd`/lib64:`pwd`/lib32:$LD_LIBRARY_PATH"' else @@ -154,7 +154,7 @@ export SL_OPT="`cat gridargs.dat` $@" eval ${SL_ENV} ${SL_CMD} ${SL_OPT} || LL_RUN_ERR=runerr # Handle any resulting errors -if [ -n "$LL_RUN_ERR" = "runerr" ]; then +if [ -n "$LL_RUN_ERR" ]; then # generic error running the binary echo '*** Bad shutdown. ***' fi diff --git a/indra/newview/llfloaterstats.cpp b/indra/newview/llfloaterstats.cpp index a4311897e..342e4fa45 100644 --- a/indra/newview/llfloaterstats.cpp +++ b/indra/newview/llfloaterstats.cpp @@ -247,7 +247,8 @@ void LLFloaterStats::buildStats() stat_barp = net_statviewp->addStat("HTTP Textures", &(LLViewerStats::getInstance()->mHTTPTextureKBitStat), "DebugStatModeHTTPTexture"); stat_barp->setUnitLabel(" kbps"); stat_barp->mMinBar = 0.f; - stat_barp->mMaxBar = gSavedSettings.getF32("HTTPThrottleBandwidth") * 2; // Times two because we'll have over shoots. + stat_barp->mMaxBar = gSavedSettings.getF32("HTTPThrottleBandwidth"); + stat_barp->mMaxBar *= llclamp(2.0 - (stat_barp->mMaxBar - 400.f) / 3600.f, 1.0, 2.0); // Allow for overshoot (allow more for low bandwidth values). stat_barp->mTickSpacing = 1.f; while (stat_barp->mTickSpacing < stat_barp->mMaxBar / 8) stat_barp->mTickSpacing *= 2.f; @@ -262,7 +263,7 @@ void LLFloaterStats::buildStats() stat_barp->mTickSpacing = 128.f; stat_barp->mLabelSpacing = 256.f; - stat_barp = net_statviewp->addStat("Objects", &(LLViewerStats::getInstance()->mObjectKBitStat), "DebugStatModeObjects"); + stat_barp = net_statviewp->addStat("Objects (UDP)", &(LLViewerStats::getInstance()->mObjectKBitStat), "DebugStatModeObjects"); stat_barp->setUnitLabel(" kbps"); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 1024.f; diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 6b88ab5c5..272a0aad8 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -37,6 +37,7 @@ #include "llviewermessage.h" #include "llviewerregion.h" #include "llviewerwindow.h" +#include "hippogridmanager.h" class AIHTTPTimeoutPolicy; extern AIHTTPTimeoutPolicy inventoryModelFetchDescendentsResponder_timeout; @@ -115,7 +116,6 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) { // it's a folder, do a bulk fetch LL_DEBUGS("InventoryFetch") << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL; - mBackgroundFetchActive = TRUE; mFolderFetchActive = true; if (id.isNull()) { @@ -124,12 +124,14 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) mRecursiveInventoryFetchStarted |= recursive; mFetchQueue.push_back(FetchQueueInfo(gInventory.getRootFolderID(), recursive)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + mBackgroundFetchActive = TRUE; } if (!mRecursiveLibraryFetchStarted) { mRecursiveLibraryFetchStarted |= recursive; mFetchQueue.push_back(FetchQueueInfo(gInventory.getLibraryRootFolderID(), recursive)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + mBackgroundFetchActive = TRUE; } } else @@ -139,6 +141,7 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive) { mFetchQueue.push_front(FetchQueueInfo(id, recursive)); gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + mBackgroundFetchActive = TRUE; } if (id == gInventory.getLibraryRootFolderID()) { @@ -178,6 +181,11 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched() mAllFoldersFetched = TRUE; } mFolderFetchActive = false; + if (mBackgroundFetchActive) + { + gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); + mBackgroundFetchActive = FALSE; + } } void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *) @@ -190,14 +198,27 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() LLViewerRegion* region = gAgent.getRegion(); if (mBackgroundFetchActive && region && region->capabilitiesReceived()) { - // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. - std::string url = region->getCapability("FetchInventory2"); - if (gSavedSettings.getBOOL("UseHTTPInventory") && !url.empty()) + if (gSavedSettings.getBOOL("UseHTTPInventory")) { - bulkFetch(); - return; - } - + // If we'll be using the capability, we'll be sending batches and the background thing isn't as important. + std::string url = region->getCapability("FetchInventory2"); + if (!url.empty()) + { + if (!mPerServicePtr) + { + // One time initialization needed for bulkFetch(). + std::string servicename = AIPerService::extract_canonical_servicename(url); + if (!servicename.empty()) + { + llinfos << "Initialized service name for bulk inventory fetching with \"" << servicename << "\"." << llendl; + mPerServicePtr = AIPerService::instance(servicename); + } + } + bulkFetch(); + return; + } + } + #if 1 //-------------------------------------------------------------------------------- // DEPRECATED OLD CODE @@ -207,10 +228,7 @@ void LLInventoryModelBackgroundFetch::backgroundFetch() if (mFetchQueue.empty()) { llinfos << "Inventory fetch completed" << llendl; - setAllFoldersFetched(); - mBackgroundFetchActive = false; - mFolderFetchActive = false; return; } @@ -395,7 +413,6 @@ class LLInventoryModelFetchDescendentsResponder : public LLHTTPClient::Responder mRequestSD(request_sd), mRecursiveCatUUIDs(recursive_cats) {}; - //LLInventoryModelFetchDescendentsResponder() {}; /*virtual*/ void result(const LLSD& content); /*virtual*/ void error(U32 status, const std::string& reason); /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return inventoryModelFetchDescendentsResponder_timeout; } @@ -575,28 +592,20 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat } // Bundle up a bunch of requests to send all at once. -// static void LLInventoryModelBackgroundFetch::bulkFetch() { //Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped. //If there are items in mFetchQueue, we want to check the time since the last bulkFetch was //sent. If it exceeds our retry time, go ahead and fire off another batch. LLViewerRegion* region = gAgent.getRegion(); - if (!region) return; + if (gDisconnected || !region) return; - S16 max_concurrent_fetches=8; - F32 new_min_time = 0.5f; //HACK! Clean this up when old code goes away entirely. - if (mMinTimeBetweenFetches < new_min_time) + static LLCachedControl const throttle_bandwidth("HTTPThrottleBandwidth", 2000); + bool const no_bandwidth_throttling = gHippoGridManager->getConnectedGrid()->isAvination(); + if (!AIPerService::wantsMoreHTTPRequestsFor(mPerServicePtr, throttle_bandwidth, no_bandwidth_throttling)) { - mMinTimeBetweenFetches=new_min_time; //HACK! See above. + return; // Wait. } - - if (gDisconnected || - (mFetchCount > max_concurrent_fetches) || - (mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches)) - { - return; // just bail if we are disconnected - } U32 item_count=0; U32 folder_count=0; @@ -708,6 +717,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() { mFetchCount++; url = region->getCapability("FetchInventory2"); + llassert(!url.empty()); if (!url.empty()) { LLSD body; @@ -716,18 +726,6 @@ void LLInventoryModelBackgroundFetch::bulkFetch() LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body)); } - //else - //{ - // LLMessageSystem* msg = gMessageSystem; - // msg->newMessage("FetchInventory"); - // msg->nextBlock("AgentData"); - // msg->addUUID("AgentID", gAgent.getID()); - // msg->addUUID("SessionID", gAgent.getSessionID()); - // msg->nextBlock("InventoryData"); - // msg->addUUID("OwnerID", mPermissions.getOwner()); - // msg->addUUID("ItemID", mUUID); - // gAgent.sendReliableMessage(); - //} } if (item_request_body_lib.size()) @@ -735,6 +733,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() mFetchCount++; url = region->getCapability("FetchLib2"); + llassert(!url.empty()); if (!url.empty()) { LLSD body; @@ -750,6 +749,7 @@ void LLInventoryModelBackgroundFetch::bulkFetch() else if (isBulkFetchProcessingComplete()) { + llinfos << "Inventory fetch completed" << llendl; setAllFoldersFetched(); } } diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index bc40cc5cb..4056bdfbd 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -29,6 +29,7 @@ #include "llsingleton.h" #include "lluuid.h" +#include "aicurlperservice.h" //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLInventoryModelBackgroundFetch @@ -75,12 +76,14 @@ private: BOOL mRecursiveLibraryFetchStarted; BOOL mAllFoldersFetched; - BOOL mBackgroundFetchActive; + BOOL mBackgroundFetchActive; // TRUE if LLInventoryModelBackgroundFetch::backgroundFetchCB is being called from idle(). bool mFolderFetchActive; S16 mFetchCount; BOOL mTimelyFetchPending; S32 mNumFetchRetries; + AIPerServicePtr mPerServicePtr; // Pointer to the AIPerService corresponding to the FetchInventory2 capability. + LLFrameTimer mFetchTimer; F32 mMinTimeBetweenFetches; F32 mMaxTimeBetweenFetches; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index c7603dc26..f80bd9539 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -1172,7 +1172,7 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { - // This will happen if not logged in or if a region deoes not have HTTP Texture enabled + // This will happen if not logged in or if a region does not have HTTP Texture enabled //llwarns << "Region not found for host: " << mHost << llendl; mCanUseHTTP = false; } @@ -2034,7 +2034,6 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mBadPacketCount(0), mTextureCache(cache), mImageDecodeThread(imagedecodethread), - mHTTPTextureBits(0), mTotalHTTPRequests(0), mQAMode(qa_mode), mTotalCacheReadCount(0U), @@ -2186,7 +2185,6 @@ void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id, S32 received_size) { LLMutexLock lock(&mNetworkQueueMutex); mHTTPTextureQueue.erase(id); - mHTTPTextureBits += received_size * 8; // Approximate - does not include header bits } void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) @@ -2399,15 +2397,6 @@ void LLTextureFetch::commonUpdate() //virtual S32 LLTextureFetch::update(F32 max_time_ms) { - { - mNetworkQueueMutex.lock() ; - - gTextureList.sTextureBits += mHTTPTextureBits ; - mHTTPTextureBits = 0 ; - - mNetworkQueueMutex.unlock() ; - } - S32 res = LLWorkerThread::update(max_time_ms); if (!mDebugPause) diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index d7cc94dcd..4062c310a 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -163,8 +163,6 @@ private: cancel_queue_t mCancelQueue; LLTextureInfo mTextureInfo; - U32 mHTTPTextureBits; - //debug use U32 mTotalHTTPRequests ; diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index eb3e35997..97ea6d71a 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -353,22 +353,25 @@ void LLViewerInventoryItem::fetchFromServer(void) const { std::string url; - LLViewerRegion* region = gAgent.getRegion(); - // we have to check region. It can be null after region was destroyed. See EXT-245 - if (region) + if (gSavedSettings.getBOOL("UseHTTPInventory")) { - if(gAgent.getID() != mPermissions.getOwner()) - { - url = region->getCapability("FetchLib2"); - } - else - { - url = region->getCapability("FetchInventory2"); - } - } - else - { - llwarns << "Agent Region is absent" << llendl; + LLViewerRegion* region = gAgent.getRegion(); + // we have to check region. It can be null after region was destroyed. See EXT-245 + if (region) + { + if(gAgent.getID() != mPermissions.getOwner()) + { + url = region->getCapability("FetchLib2"); + } + else + { + url = region->getCapability("FetchInventory2"); + } + } + else + { + llwarns << "Agent Region is absent" << llendl; + } } if (!url.empty()) diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 70f432f02..6c09d31e4 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1638,15 +1638,10 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("EnvironmentSettings"); capabilityNames.append("EstateChangeInfo"); capabilityNames.append("EventQueueGet"); - - if (gSavedSettings.getBOOL("UseHTTPInventory")) //Caps suffixed with 2 by LL. Don't update until rest of fetch system is updated first. - { - capabilityNames.append("FetchLib2"); - capabilityNames.append("FetchLibDescendents2"); - capabilityNames.append("FetchInventory2"); - capabilityNames.append("FetchInventoryDescendents2"); - } - + capabilityNames.append("FetchLib2"); + capabilityNames.append("FetchLibDescendents2"); + capabilityNames.append("FetchInventory2"); + capabilityNames.append("FetchInventoryDescendents2"); capabilityNames.append("GamingData"); //Used by certain grids. capabilityNames.append("GetDisplayNames"); capabilityNames.append("GetMesh");