From 5fb224bb8196e77259bef2a0ef60e82533c358a2 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 30 Aug 2011 09:52:25 -0400 Subject: CHOP-763: make sendReply() treat replyKey as optional. It's not worth bothering to tweak reply LLSD or attempt to send it if the incoming request has no replyKey, in effect not requesting a reply. This supports LLEventAPI operations for which the caller might or might not care about a reply, invoked using either send() (fire and forget) or request() (send request, wait for response). This logic should be central, instead of having to perform that test in every caller that cares. The major alternative would have been to treat missing replyKey as an error (whether LL_ERRS or exception). But since there's already a mechanism by which an LLEventAPI operation method can stipulate its replyKey as required, at this level we can let it be optional. --- indra/llcommon/llevents.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index ff03506e84..db1ea4792b 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -591,6 +591,17 @@ void LLReqID::stamp(LLSD& response) const bool sendReply(const LLSD& reply, const LLSD& request, const std::string& replyKey) { + // If the original request has no value for replyKey, it's pointless to + // construct or send a reply event: on which LLEventPump should we send + // it? Allow that to be optional: if the caller wants to require replyKey, + // it can so specify when registering the operation method. + if (! request.has(replyKey)) + { + return false; + } + + // Here the request definitely contains replyKey; reasonable to proceed. + // Copy 'reply' to modify it. LLSD newreply(reply); // Get the ["reqid"] element from request -- cgit v1.2.3 From 3ddf3aef9b2f2bb85932bd33b9daac5e59d3018a Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Thu, 1 Sep 2011 13:12:23 -0400 Subject: CHOP-763: Promote Response class from llwindowlistener.cpp to LLEventAPI. This is a generally-useful idiom, extending the sendReply() convenience function -- it shouldn't remain buried in a single .cpp file. --- indra/llcommon/lleventapi.cpp | 30 +++++++++++++++++ indra/llcommon/lleventapi.h | 78 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) (limited to 'indra/llcommon') diff --git a/indra/llcommon/lleventapi.cpp b/indra/llcommon/lleventapi.cpp index 4270c8b511..ff5459c1eb 100644 --- a/indra/llcommon/lleventapi.cpp +++ b/indra/llcommon/lleventapi.cpp @@ -34,6 +34,7 @@ // std headers // external library headers // other Linden headers +#include "llerror.h" LLEventAPI::LLEventAPI(const std::string& name, const std::string& desc, const std::string& field): lbase(name, field), @@ -45,3 +46,32 @@ LLEventAPI::LLEventAPI(const std::string& name, const std::string& desc, const s LLEventAPI::~LLEventAPI() { } + +LLEventAPI::Response::Response(const LLSD& seed, const LLSD& request, const LLSD::String& replyKey): + mResp(seed), + mReq(request), + mKey(replyKey) +{} + +LLEventAPI::Response::~Response() +{ + // When you instantiate a stack Response object, if the original + // request requested a reply, send it when we leave this block, no + // matter how. + sendReply(mResp, mReq, mKey); +} + +void LLEventAPI::Response::warn(const std::string& warning) +{ + LL_WARNS("LLEventAPI::Response") << warning << LL_ENDL; + mResp["warnings"].append(warning); +} + +void LLEventAPI::Response::error(const std::string& error) +{ + // Use LL_WARNS rather than LL_ERROR: we don't want the viewer to shut + // down altogether. + LL_WARNS("LLEventAPI::Response") << error << LL_ENDL; + + mResp["error"] = error; +} diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h index d75d521e8e..332dee9550 100644 --- a/indra/llcommon/lleventapi.h +++ b/indra/llcommon/lleventapi.h @@ -76,6 +76,84 @@ public: LLEventDispatcher::add(name, desc, callable, required); } + /** + * Instantiate a Response object in any LLEventAPI subclass method that + * wants to guarantee a reply (if requested) will be sent on exit from the + * method. The reply will be sent if request.has(@a replyKey), default + * "reply". If specified, the value of request[replyKey] is the name of + * the LLEventPump on which to send the reply. Conventionally you might + * code something like: + * + * @code + * void MyEventAPI::someMethod(const LLSD& request) + * { + * // Send a reply event as long as request.has("reply") + * Response response(LLSD(), request); + * // ... + * // will be sent in reply event + * response["somekey"] = some_data; + * } + * @endcode + */ + class Response + { + public: + /** + * Instantiating a Response object in an LLEventAPI subclass method + * ensures that, if desired, a reply event will be sent. + * + * @a seed is the initial reply LLSD that will be further decorated before + * being sent as the reply + * + * @a request is the incoming request LLSD; we particularly care about + * [replyKey] and ["reqid"] + * + * @a replyKey [default "reply"] is the string name of the LLEventPump + * on which the caller wants a reply. If (! + * request.has(replyKey)), no reply will be sent. + */ + Response(const LLSD& seed, const LLSD& request, const LLSD::String& replyKey="reply"); + ~Response(); + + /** + * @code + * if (some condition) + * { + * response.warn("warnings are logged and collected in [\"warnings\"]"); + * } + * @endcode + */ + void warn(const std::string& warning); + /** + * @code + * if (some condition isn't met) + * { + * // In a function returning void, you can validly 'return + * // expression' if the expression is itself of type void. But + * // returning is up to you; response.error() has no effect on + * // flow of control. + * return response.error("error message, logged and also sent as [\"error\"]"); + * } + * @endcode + */ + void error(const std::string& error); + + /** + * set other keys... + * + * @code + * // set any attributes you want to be sent in the reply + * response["info"] = some_value; + * // ... + * response["ok"] = went_well; + * @endcode + */ + LLSD& operator[](const LLSD::String& key) { return mResp[key]; } + + LLSD mResp, mReq; + LLSD::String mKey; + }; + private: std::string mDesc; }; -- cgit v1.2.3 From ecba41419f6470cc3d85bbb277ef88ebbf266feb Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 6 Sep 2011 13:25:27 -0400 Subject: CHOP-763: Nested LLEventAPI::Response class needs LL_COMMON_API too. Apparently the outer class's LL_COMMON_API marker affects all outer class members, but not nested classes. Making it explicit fixes Windows link errors. --- indra/llcommon/lleventapi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h index 332dee9550..64d038ade4 100644 --- a/indra/llcommon/lleventapi.h +++ b/indra/llcommon/lleventapi.h @@ -95,7 +95,7 @@ public: * } * @endcode */ - class Response + class LL_COMMON_API Response { public: /** -- cgit v1.2.3 From 616a7b549d21624e6667218efe29c1e552f9b375 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 7 Sep 2011 23:23:08 -0600 Subject: fix for VWR-26864: Recent commit to Snowstorm project introduces frequent errors and crashes associated with private memory pool. --- indra/llcommon/llmemory.cpp | 95 ++++++++++++++++++++++++++++++++++----------- indra/llcommon/llmemory.h | 11 +++--- 2 files changed, 79 insertions(+), 27 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 8c02ad8290..3b27a1639a 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -165,33 +165,60 @@ void LLMemory::logMemoryInfo(BOOL update) llinfos << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << llendl ; llinfos << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << llendl ; llinfos << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << llendl ; + + llinfos << "--- private pool information -- " << llendl ; + llinfos << "Total reserved (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024 << llendl ; + llinfos << "Total allocated (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024 << llendl ; } //return 0: everything is normal; //return 1: the memory pool is low, but not in danger; //return -1: the memory pool is in danger, is about to crash. //static -S32 LLMemory::isMemoryPoolLow() +bool LLMemory::isMemoryPoolLow() { static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use + const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB + static void* last_reserved_address = NULL ; if(!sEnableMemoryFailurePrevention) { - return 0 ; //no memory failure prevention. + return false ; //no memory failure prevention. } if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory { - return -1 ; + return true ; } if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space. { - return -1 ; + return true ; } - return (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB || + bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB || sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ; + + //check the virtual address space fragmentation + if(!is_low) + { + if(!last_reserved_address) + { + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + } + else + { + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + if(!last_reserved_address) //failed, try once more + { + last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ; + } + } + + is_low = !last_reserved_address ; //allocation failed + } + + return is_low ; } //static @@ -1289,15 +1316,13 @@ U16 LLPrivateMemoryPool::LLMemoryChunk::getPageLevel(U32 size) //-------------------------------------------------------------------- const U32 CHUNK_SIZE = 4 << 20 ; //4 MB const U32 LARGE_CHUNK_SIZE = 4 * CHUNK_SIZE ; //16 MB -LLPrivateMemoryPool::LLPrivateMemoryPool(S32 type) : +LLPrivateMemoryPool::LLPrivateMemoryPool(S32 type, U32 max_pool_size) : mMutexp(NULL), mReservedPoolSize(0), mHashFactor(1), - mType(type) + mType(type), + mMaxPoolSize(max_pool_size) { - const U32 MAX_POOL_SIZE = 256 * 1024 * 1024 ; //256 MB - - mMaxPoolSize = MAX_POOL_SIZE ; if(type == STATIC_THREADED || type == VOLATILE_THREADED) { mMutexp = new LLMutex ; @@ -1362,16 +1387,31 @@ char* LLPrivateMemoryPool::allocate(U32 size) chunk = chunk->mNext ; } } - - chunk = addChunk(chunk_idx) ; - if(chunk) + else { - p = chunk->allocate(size) ; + chunk = addChunk(chunk_idx) ; + if(chunk) + { + p = chunk->allocate(size) ; + } } } unlock() ; + if(!p) //to get memory from the private pool failed, try the heap directly + { + static bool to_log = true ; + + if(to_log) + { + llwarns << "The memory pool overflows, now using heap directly!" << llendl ; + to_log = false ; + } + + return (char*)malloc(size) ; + } + return p ; } @@ -1472,7 +1512,7 @@ void LLPrivateMemoryPool::destroyPool() unlock() ; } -void LLPrivateMemoryPool::checkSize(U32 asked_size) +bool LLPrivateMemoryPool::checkSize(U32 asked_size) { if(mReservedPoolSize + asked_size > mMaxPoolSize) { @@ -1480,8 +1520,12 @@ void LLPrivateMemoryPool::checkSize(U32 asked_size) llinfos << "Total reserved size: " << mReservedPoolSize + asked_size << llendl ; llinfos << "Total_allocated Size: " << getTotalAllocatedSize() << llendl ; - llerrs << "The pool is overflowing..." << llendl ; + //llerrs << "The pool is overflowing..." << llendl ; + + return false ; } + + return true ; } LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_index) @@ -1501,7 +1545,11 @@ LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_inde MAX_SLOT_SIZES[chunk_index], MIN_BLOCK_SIZES[chunk_index], MAX_BLOCK_SIZES[chunk_index]) ; } - checkSize(preferred_size + overhead) ; + if(!checkSize(preferred_size + overhead)) + { + return NULL ; + } + mReservedPoolSize += preferred_size + overhead ; char* buffer = (char*)malloc(preferred_size + overhead) ; @@ -1593,7 +1641,7 @@ LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::findChunk(const char* a void LLPrivateMemoryPool::addToHashTable(LLMemoryChunk* chunk) { - static const U16 HASH_FACTORS[] = {41, 83, 193, 317, 419, 523, 0xFFFF}; + static const U16 HASH_FACTORS[] = {41, 83, 193, 317, 419, 523, 719, 997, 1523, 0xFFFF}; U16 i ; if(mChunkHashList.empty()) @@ -1774,7 +1822,7 @@ void LLPrivateMemoryPool::LLChunkHashElement::remove(LLPrivateMemoryPool::LLMemo //-------------------------------------------------------------------- LLPrivateMemoryPoolManager* LLPrivateMemoryPoolManager::sInstance = NULL ; -LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled) +LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled, U32 max_pool_size) { mPoolList.resize(LLPrivateMemoryPool::MAX_TYPES) ; @@ -1784,6 +1832,9 @@ LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled) } mPrivatePoolEnabled = enabled ; + + const U32 MAX_POOL_SIZE = 256 * 1024 * 1024 ; //256 MB + mMaxPrivatePoolSize = llmax(max_pool_size, MAX_POOL_SIZE) ; } LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager() @@ -1826,11 +1877,11 @@ LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager() } //static -void LLPrivateMemoryPoolManager::initClass(BOOL enabled) +void LLPrivateMemoryPoolManager::initClass(BOOL enabled, U32 max_pool_size) { llassert_always(!sInstance) ; - sInstance = new LLPrivateMemoryPoolManager(enabled) ; + sInstance = new LLPrivateMemoryPoolManager(enabled, max_pool_size) ; } //static @@ -1862,7 +1913,7 @@ LLPrivateMemoryPool* LLPrivateMemoryPoolManager::newPool(S32 type) if(!mPoolList[type]) { - mPoolList[type] = new LLPrivateMemoryPool(type) ; + mPoolList[type] = new LLPrivateMemoryPool(type, mMaxPrivatePoolSize) ; } return mPoolList[type] ; diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index db753f0d8b..6967edd7e7 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -122,7 +122,7 @@ public: static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure); static void updateMemoryInfo() ; static void logMemoryInfo(BOOL update = FALSE); - static S32 isMemoryPoolLow(); + static bool isMemoryPoolLow(); static U32 getAvailableMemKB() ; static U32 getMaxMemKB() ; @@ -303,7 +303,7 @@ public: } ; private: - LLPrivateMemoryPool(S32 type) ; + LLPrivateMemoryPool(S32 type, U32 max_pool_size) ; ~LLPrivateMemoryPool() ; char *allocate(U32 size) ; @@ -320,7 +320,7 @@ private: void unlock() ; S32 getChunkIndex(U32 size) ; LLMemoryChunk* addChunk(S32 chunk_index) ; - void checkSize(U32 asked_size) ; + bool checkSize(U32 asked_size) ; void removeChunk(LLMemoryChunk* chunk) ; U16 findHashKey(const char* addr); void addToHashTable(LLMemoryChunk* chunk) ; @@ -383,12 +383,12 @@ private: class LL_COMMON_API LLPrivateMemoryPoolManager { private: - LLPrivateMemoryPoolManager(BOOL enabled) ; + LLPrivateMemoryPoolManager(BOOL enabled, U32 max_pool_size) ; ~LLPrivateMemoryPoolManager() ; public: static LLPrivateMemoryPoolManager* getInstance() ; - static void initClass(BOOL enabled) ; + static void initClass(BOOL enabled, U32 pool_size) ; static void destroyClass() ; LLPrivateMemoryPool* newPool(S32 type) ; @@ -398,6 +398,7 @@ private: static LLPrivateMemoryPoolManager* sInstance ; std::vector mPoolList ; BOOL mPrivatePoolEnabled; + U32 mMaxPrivatePoolSize; public: //debug and statistics info. -- cgit v1.2.3 From 2d19a2002501d44ce18080b6f26ceaf2dbf796e9 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Thu, 8 Sep 2011 09:46:04 -0500 Subject: add getInfo to LLView to get state information about ui elements. --- indra/llcommon/lleventapi.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'indra/llcommon') diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h index 64d038ade4..1a37d780b6 100644 --- a/indra/llcommon/lleventapi.h +++ b/indra/llcommon/lleventapi.h @@ -149,6 +149,11 @@ public: * @endcode */ LLSD& operator[](const LLSD::String& key) { return mResp[key]; } + + /** + * set the response to the given data + */ + void setResponse(LLSD const & response){ mResp = response; } LLSD mResp, mReq; LLSD::String mKey; -- cgit v1.2.3 From 4e228b7d661b49d4949bb64d36b2aad2e893e193 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 4 Oct 2011 06:52:55 -0400 Subject: increment viewer version to 3.1.0 --- indra/llcommon/llversionviewer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index a4b2e06908..3377465bb6 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -28,8 +28,8 @@ #define LL_LLVERSIONVIEWER_H const S32 LL_VERSION_MAJOR = 3; -const S32 LL_VERSION_MINOR = 0; -const S32 LL_VERSION_PATCH = 6; +const S32 LL_VERSION_MINOR = 1; +const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; -- cgit v1.2.3 From d0e36ade5bb16e9e5a6aca9ee4f02fbe995cdfd8 Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Tue, 4 Oct 2011 06:53:34 -0400 Subject: increment viewer version to 3.1.1 --- indra/llcommon/llversionviewer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 3377465bb6..e4ad7f4f54 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -29,7 +29,7 @@ const S32 LL_VERSION_MAJOR = 3; const S32 LL_VERSION_MINOR = 1; -const S32 LL_VERSION_PATCH = 0; +const S32 LL_VERSION_PATCH = 1; const S32 LL_VERSION_BUILD = 0; const char * const LL_CHANNEL = "Second Life Developer"; -- cgit v1.2.3 From 5ef05e151d24e15a175d4f78ff17b6abdd36bbc4 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Wed, 5 Oct 2011 15:21:10 -0600 Subject: fix for SH-2434: Mac viewer sometimes freezes at start up and must be force quit. --- indra/llcommon/llqueuedthread.cpp | 7 ++++++- indra/llcommon/llqueuedthread.h | 2 +- indra/llcommon/llworkerthread.cpp | 4 ++-- indra/llcommon/llworkerthread.h | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index efd9c4b68f..5dee7a3541 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -32,7 +32,7 @@ //============================================================================ // MAIN THREAD -LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : +LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) : LLThread(name), mThreaded(threaded), mIdleThread(TRUE), @@ -41,6 +41,11 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : { if (mThreaded) { + if(should_pause) + { + pause() ; //call this before start the thread. + } + start(); } } diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index a53b22f6fc..499d13a792 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -149,7 +149,7 @@ public: static handle_t nullHandle() { return handle_t(0); } public: - LLQueuedThread(const std::string& name, bool threaded = true); + LLQueuedThread(const std::string& name, bool threaded = true, bool should_pause = false); virtual ~LLQueuedThread(); virtual void shutdown(); diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 6b308bb917..e186621503 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -34,8 +34,8 @@ //============================================================================ // Run on MAIN thread -LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) : - LLQueuedThread(name, threaded) +LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) : + LLQueuedThread(name, threaded, should_pause) { mDeleteMutex = new LLMutex; } diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index bef5ef53fe..973b78ca01 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -83,7 +83,7 @@ private: LLMutex* mDeleteMutex; public: - LLWorkerThread(const std::string& name, bool threaded = true); + LLWorkerThread(const std::string& name, bool threaded = true, bool should_pause = false); ~LLWorkerThread(); /*virtual*/ S32 update(U32 max_time_ms); -- cgit v1.2.3