Commits

dessie linden committed 5465048 Merge

reconciled .hgtags

Comments (0)

Files changed (99)

 c7282e59f374ee904bd793c3c444455e3399b0c5 3.1.0-start
 2657fa785bbfac115852c41bd0adaff74c2ad5da DRTVWR-93_3.1.0-beta1
 2657fa785bbfac115852c41bd0adaff74c2ad5da 3.1.0-beta1
+dbaaef19266478a20654c46395300640163e98e3 DRTVWR-96_3.1.0-beta2
+dbaaef19266478a20654c46395300640163e98e3 3.1.0-beta2
+dbaaef19266478a20654c46395300640163e98e3 DRTVWR-96_3.1.0-beta2
+bc01ee26fd0f1866e266429e85f76340523e91f1 DRTVWR-96_3.1.0-beta2
+dbaaef19266478a20654c46395300640163e98e3 3.1.0-beta2
+bc01ee26fd0f1866e266429e85f76340523e91f1 3.1.0-beta2

doc/contributions.txt

 Alejandro Rosenthal
 	VWR-1184
 Aleric Inglewood
-	SNOW-84
 	SNOW-240
-	SNOW-477
 	SNOW-522
 	SNOW-626
-	SNOW-744
 	SNOW-756
 	SNOW-764
-	SNOW-766
 	SNOW-800
 	VWR-10001
 	VWR-10579
 	VWR-24366
 	VWR-24519
 	VWR-24520
+	SNOW-84
+	SNOW-477
+	SNOW-744
+	SNOW-766
 	STORM-163
-	STORM-864
 	STORM-955
 	STORM-960
 Ales Beaumont

indra/llaudio/llaudioengine_fmod.cpp

 		return false;
 	}
 
-	if (!LLAPRFile::isExist(filename, LL_APR_RPB))
+	if (!LLAPRFile::isExist(filename, NULL, LL_APR_RPB))
 	{
 		// File not found, abort.
 		return false;

indra/llaudio/llvorbisencode.cpp

 	error_msg.clear();
 
 	//********************************
-	LLAPRFile infile(in_fname, LL_APR_RB);
+	LLAPRFile infile ;
+    infile.open(in_fname,LL_APR_RB);
 	//********************************
 	if (!infile.getFileHandle())
 	{
 
 	S32 data_left = 0;
 
-	LLAPRFile infile(in_fname,LL_APR_RB);
+	LLAPRFile infile ;
+	infile.open(in_fname,LL_APR_RB);
 	if (!infile.getFileHandle())
 	{
 		llwarns << "Couldn't open temporary ogg file for writing: " << in_fname
 		return(LLVORBISENC_SOURCE_OPEN_ERR);
 	}
 
-	LLAPRFile outfile(out_fname, LL_APR_WPB);
+	LLAPRFile outfile ;
+	outfile.open(out_fname,LL_APR_WPB);
 	if (!outfile.getFileHandle())
 	{
 		llwarns << "Couldn't open upload sound file for reading: " << in_fname

indra/llcharacter/llbvhloader.cpp

 	//--------------------------------------------------------------------
 	std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName);
 
-	LLAPRFile infile(path, LL_APR_R);
+	LLAPRFile infile ;
+	infile.open(path, LL_APR_R);
 	apr_file_t *fp = infile.getFileHandle();
 	if (!fp)
 		return E_ST_NO_XLT_FILE;

indra/llcharacter/llkeyframemotionparam.cpp

 	// open the file
 	//-------------------------------------------------------------------------
 	S32 fileSize = 0;
-	LLAPRFile infile(path, LL_APR_R, &fileSize);
+	LLAPRFile infile ;
+	infile.open(path, LL_APR_R, NULL, &fileSize);
 	apr_file_t* fp = infile.getFileHandle() ;
 	if (!fp || fileSize == 0)
 	{

indra/llcharacter/llstatemachine.cpp

 
 BOOL LLStateDiagram::saveDotFile(const std::string& filename)
 {
-	LLAPRFile outfile(filename, LL_APR_W);
+	LLAPRFile outfile ;
+	outfile.open(filename, LL_APR_W);
 	apr_file_t* dot_file = outfile.getFileHandle() ;
 
 	if (!dot_file)

indra/llcommon/CMakeLists.txt

     llallocator_heap_profile.cpp
     llapp.cpp
     llapr.cpp
-    llaprpool.cpp
     llassettype.cpp
     llavatarname.cpp
     llbase32.cpp
     llrand.cpp
     llrefcount.cpp
     llrun.cpp
-    llscopedvolatileaprpool.h
     llsd.cpp
     llsdserialize.cpp
     llsdserialize_xml.cpp
     llavatarname.h
     llapp.h
     llapr.h
-    llaprpool.h
     llassettype.h
     llassoclist.h
     llavatarconstants.h

indra/llcommon/llapp.cpp

 		mOptions.append(sd);
 	}
 
+	// Make sure we clean up APR when we exit
+	// Don't need to do this if we're cleaning up APR in the destructor
+	//atexit(ll_cleanup_apr);
+
 	// Set the application to this instance.
 	sApplication = this;
 	

indra/llcommon/llapr.cpp

 #include "linden_common.h"
 #include "llapr.h"
 #include "apr_dso.h"
-#include "llscopedvolatileaprpool.h"
 
+apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
+LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
+apr_thread_mutex_t *gLogMutexp = NULL;
+apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
+
+const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
+
+void ll_init_apr()
+{
+	if (!gAPRPoolp)
+	{
+		// Initialize APR and create the global pool
+		apr_initialize();
+		apr_pool_create(&gAPRPoolp, NULL);
+		
+		// Initialize the logging mutex
+		apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
+		apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
+	}
+
+	if(!LLAPRFile::sAPRFilePoolp)
+	{
+		LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ;
+	}
+}
+
+
+void ll_cleanup_apr()
+{
+	LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
+
+	if (gLogMutexp)
+	{
+		// Clean up the logging mutex
+
+		// All other threads NEED to be done before we clean up APR, so this is okay.
+		apr_thread_mutex_destroy(gLogMutexp);
+		gLogMutexp = NULL;
+	}
+	if (gCallStacksLogMutexp)
+	{
+		// Clean up the logging mutex
+
+		// All other threads NEED to be done before we clean up APR, so this is okay.
+		apr_thread_mutex_destroy(gCallStacksLogMutexp);
+		gCallStacksLogMutexp = NULL;
+	}
+	if (gAPRPoolp)
+	{
+		apr_pool_destroy(gAPRPoolp);
+		gAPRPoolp = NULL;
+	}
+	if (LLAPRFile::sAPRFilePoolp)
+	{
+		delete LLAPRFile::sAPRFilePoolp ;
+		LLAPRFile::sAPRFilePoolp = NULL ;
+	}
+	apr_terminate();
+}
+
+//
+//
+//LLAPRPool
+//
+LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) 	
+	: mParent(parent),
+	mReleasePoolFlag(releasePoolFlag),
+	mMaxSize(size),
+	mPool(NULL)
+{	
+	createAPRPool() ;
+}
+
+LLAPRPool::~LLAPRPool() 
+{
+	releaseAPRPool() ;
+}
+
+void LLAPRPool::createAPRPool()
+{
+	if(mPool)
+	{
+		return ;
+	}
+
+	mStatus = apr_pool_create(&mPool, mParent);
+	ll_apr_warn_status(mStatus) ;
+
+	if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes.
+	{
+		apr_allocator_t *allocator = apr_pool_allocator_get(mPool); 
+		if (allocator) 
+		{ 
+			apr_allocator_max_free_set(allocator, mMaxSize) ;
+		}
+	}
+}
+
+void LLAPRPool::releaseAPRPool()
+{
+	if(!mPool)
+	{
+		return ;
+	}
+
+	if(!mParent || mReleasePoolFlag)
+	{
+		apr_pool_destroy(mPool) ;
+		mPool = NULL ;
+	}
+}
+
+//virtual
+apr_pool_t* LLAPRPool::getAPRPool() 
+{	
+	return mPool ; 
+}
+
+LLVolatileAPRPool::LLVolatileAPRPool(BOOL is_local, apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag) 
+				  : LLAPRPool(parent, size, releasePoolFlag),
+				  mNumActiveRef(0),
+				  mNumTotalRef(0),
+				  mMutexPool(NULL),
+				  mMutexp(NULL)
+{
+	//create mutex
+	if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
+	{
+		apr_pool_create(&mMutexPool, NULL); // Create a pool for mutex
+		apr_thread_mutex_create(&mMutexp, APR_THREAD_MUTEX_UNNESTED, mMutexPool);
+	}
+}
+
+LLVolatileAPRPool::~LLVolatileAPRPool()
+{
+	//delete mutex
+	if(mMutexp)
+	{
+		apr_thread_mutex_destroy(mMutexp);
+		apr_pool_destroy(mMutexPool);
+	}
+}
+
+//
+//define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
+//
+//virtual 
+apr_pool_t* LLVolatileAPRPool::getAPRPool() 
+{
+	return LLVolatileAPRPool::getVolatileAPRPool() ;
+}
+
+apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool() 
+{	
+	LLScopedLock lock(mMutexp) ;
+
+	mNumTotalRef++ ;
+	mNumActiveRef++ ;
+
+	if(!mPool)
+	{
+		createAPRPool() ;
+	}
+	
+	return mPool ;
+}
+
+void LLVolatileAPRPool::clearVolatileAPRPool() 
+{
+	LLScopedLock lock(mMutexp) ;
+
+	if(mNumActiveRef > 0)
+	{
+		mNumActiveRef--;
+		if(mNumActiveRef < 1)
+		{
+			if(isFull()) 
+			{
+				mNumTotalRef = 0 ;
+
+				//destroy the apr_pool.
+				releaseAPRPool() ;
+			}
+			else 
+			{
+				//This does not actually free the memory, 
+				//it just allows the pool to re-use this memory for the next allocation. 
+				apr_pool_clear(mPool) ;
+			}
+		}
+	}
+	else
+	{
+		llassert_always(mNumActiveRef > 0) ;
+	}
+
+	//paranoia check if the pool is jammed.
+	//will remove the check before going to release.
+	llassert_always(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
+}
+
+BOOL LLVolatileAPRPool::isFull()
+{
+	return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
+}
 //---------------------------------------------------------------------
 //
 // LLScopedLock
 //
 LLAPRFile::LLAPRFile()
 	: mFile(NULL),
-	  mVolatileFilePoolp(NULL),
-	  mRegularFilePoolp(NULL)
+	  mCurrentFilePoolp(NULL)
 {
 }
 
-LLAPRFile::LLAPRFile(std::string const& filename, apr_int32_t flags, S32* sizep, access_t access_type)
+LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool)
 	: mFile(NULL),
-	  mVolatileFilePoolp(NULL),
-	  mRegularFilePoolp(NULL)
+	  mCurrentFilePoolp(NULL)
 {
-	open(filename, flags, access_type, sizep);
+	open(filename, flags, pool);
 }
 
 LLAPRFile::~LLAPRFile()
 		mFile = NULL ;
 	}
 
-	if (mVolatileFilePoolp)
+	if(mCurrentFilePoolp)
 	{
-		mVolatileFilePoolp->clearVolatileAPRPool() ;
-		mVolatileFilePoolp = NULL ;
-	}
-
-	if (mRegularFilePoolp)
-	{
-		delete mRegularFilePoolp;
-		mRegularFilePoolp = NULL;
+		mCurrentFilePoolp->clearVolatileAPRPool() ;
+		mCurrentFilePoolp = NULL ;
 	}
 
 	return ret ;
 }
 
-apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep)
+apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep)
 {
-	llassert_always(!mFile);
-	llassert_always(!mVolatileFilePoolp && !mRegularFilePoolp);
+	apr_status_t s ;
 
-	apr_status_t status;
-	{
-		apr_pool_t* apr_file_open_pool;	// The use of apr_pool_t is OK here.
-										// This is a temporary variable for a pool that is passed directly to apr_file_open below.
-		if (access_type == short_lived)
-		{
-			// Use a "volatile" thread-local pool.
-			mVolatileFilePoolp = &LLThreadLocalData::tldata().mVolatileAPRPool;
-			// Access the pool and increment its reference count.
-			// The reference count of LLVolatileAPRPool objects will be decremented
-			// again in LLAPRFile::close by calling mVolatileFilePoolp->clearVolatileAPRPool().
-			apr_file_open_pool = mVolatileFilePoolp->getVolatileAPRPool();
-		}
-		else
-		{
-			mRegularFilePoolp = new LLAPRPool(LLThreadLocalData::tldata().mRootPool);
-			apr_file_open_pool = (*mRegularFilePoolp)();
-		}
-		status = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_file_open_pool);
-	}
-	if (status != APR_SUCCESS || !mFile)
+	//check if already open some file
+	llassert_always(!mFile) ;
+	llassert_always(!mCurrentFilePoolp) ;
+	
+	apr_pool_t* apr_pool = pool ? pool->getVolatileAPRPool() : NULL ;
+	s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, getAPRFilePool(apr_pool));
+
+	if (s != APR_SUCCESS || !mFile)
 	{
 		mFile = NULL ;
-		close() ;
+		
 		if (sizep)
 		{
 			*sizep = 0;
 		}
-		return status;
 	}
-
-	if (sizep)
+	else if (sizep)
 	{
 		S32 file_size = 0;
 		apr_off_t offset = 0;
 		*sizep = file_size;
 	}
 
-	return status;
+	if(!mCurrentFilePoolp)
+	{
+		mCurrentFilePoolp = pool ;
+
+		if(!mFile)
+		{
+			close() ;
+		}
+	}
+
+	return s ;
+}
+
+//use gAPRPoolp.
+apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool)
+{
+	apr_status_t s;
+
+	//check if already open some file
+	llassert_always(!mFile) ;
+	llassert_always(!mCurrentFilePoolp) ;
+	llassert_always(use_global_pool) ; //be aware of using gAPRPoolp.
+	
+	s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, gAPRPoolp);
+	if (s != APR_SUCCESS || !mFile)
+	{
+		mFile = NULL ;
+		close() ;
+		return s;
+	}
+
+	return s;
+}
+
+apr_pool_t* LLAPRFile::getAPRFilePool(apr_pool_t* pool)
+{	
+	if(!pool)
+	{
+		mCurrentFilePoolp = sAPRFilePoolp ;
+		return mCurrentFilePoolp->getVolatileAPRPool() ;
+	}
+
+	return pool ;
 }
 
 // File I/O
 //
 
 //static
+apr_status_t LLAPRFile::close(apr_file_t* file_handle, LLVolatileAPRPool* pool) 
+{
+	apr_status_t ret = APR_SUCCESS ;
+	if(file_handle)
+	{
+		ret = apr_file_close(file_handle);
+		file_handle = NULL ;
+	}
+
+	if(pool)
+	{
+		pool->clearVolatileAPRPool() ;
+	}
+
+	return ret ;
+}
+
+//static
+apr_file_t* LLAPRFile::open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
+{
+	apr_status_t s;
+	apr_file_t* file_handle ;
+
+	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
+
+	s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());
+	if (s != APR_SUCCESS || !file_handle)
+	{
+		ll_apr_warn_status(s);
+		LL_WARNS("APR") << " Attempting to open filename: " << filename << LL_ENDL;
+		file_handle = NULL ;
+		close(file_handle, pool) ;
+		return NULL;
+	}
+
+	return file_handle ;
+}
+
+//static
 S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
 {
 	if(!file_handle)
 }
 
 //static
-S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes)
+S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
 {
-	apr_file_t* file_handle;
-	LLScopedVolatileAPRPool pool;
-	apr_status_t s = apr_file_open(&file_handle, filename.c_str(), APR_READ|APR_BINARY, APR_OS_DEFAULT, pool);
-	if (s != APR_SUCCESS || !file_handle)
+	//*****************************************
+	apr_file_t* file_handle = open(filename, pool, APR_READ|APR_BINARY); 
+	//*****************************************	
+	if (!file_handle)
 	{
-		ll_apr_warn_status(s);
-		LL_WARNS("APR") << " while attempting to open file \"" << filename << '"' << LL_ENDL;
 		return 0;
 	}
 
 		}
 	}
 	
-	apr_file_close(file_handle);
-
+	//*****************************************
+	close(file_handle, pool) ; 
+	//*****************************************
 	return (S32)bytes_read;
 }
 
 //static
-S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes)
+S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
 {
 	apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
 	if (offset < 0)
 		offset = 0;
 	}
 	
-	apr_file_t* file_handle;
-	LLScopedVolatileAPRPool pool;
-	apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
-	if (s != APR_SUCCESS || !file_handle)
+	//*****************************************
+	apr_file_t* file_handle = open(filename, pool, flags);
+	//*****************************************
+	if (!file_handle)
 	{
-		ll_apr_warn_status(s);
-		LL_WARNS("APR") << " while attempting to open file \"" << filename << '"' << LL_ENDL;
 		return 0;
 	}
 
 		}
 	}
 
-	apr_file_close(file_handle);
+	//*****************************************
+	LLAPRFile::close(file_handle, pool);
+	//*****************************************
 
 	return (S32)bytes_written;
 }
 
 //static
-bool LLAPRFile::remove(const std::string& filename)
+bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
 {
 	apr_status_t s;
 
-	LLScopedVolatileAPRPool pool;
-	s = apr_file_remove(filename.c_str(), pool);
+	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
+	s = apr_file_remove(filename.c_str(), pool->getVolatileAPRPool());
+	pool->clearVolatileAPRPool() ;
 
 	if (s != APR_SUCCESS)
 	{
 }
 
 //static
-bool LLAPRFile::rename(const std::string& filename, const std::string& newname)
+bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool)
 {
 	apr_status_t s;
 
-	LLScopedVolatileAPRPool pool;
-	s = apr_file_rename(filename.c_str(), newname.c_str(), pool);
+	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
+	s = apr_file_rename(filename.c_str(), newname.c_str(), pool->getVolatileAPRPool());
+	pool->clearVolatileAPRPool() ;
 	
 	if (s != APR_SUCCESS)
 	{
 }
 
 //static
-bool LLAPRFile::isExist(const std::string& filename, apr_int32_t flags)
+bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
 {
-	apr_file_t* file_handle;
+	apr_file_t* apr_file;
 	apr_status_t s;
 
-	LLScopedVolatileAPRPool pool;
-	s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
+	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
+	s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, pool->getVolatileAPRPool());	
 
-	if (s != APR_SUCCESS || !file_handle)
+	if (s != APR_SUCCESS || !apr_file)
 	{
+		pool->clearVolatileAPRPool() ;
 		return false;
 	}
 	else
 	{
-		apr_file_close(file_handle);
+		apr_file_close(apr_file) ;
+		pool->clearVolatileAPRPool() ;
 		return true;
 	}
 }
 
 //static
-S32 LLAPRFile::size(const std::string& filename)
+S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
 {
-	apr_file_t* file_handle;
+	apr_file_t* apr_file;
 	apr_finfo_t info;
 	apr_status_t s;
 	
-	LLScopedVolatileAPRPool pool;
-	s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool);
+	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
+	s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool->getVolatileAPRPool());
 	
-	if (s != APR_SUCCESS || !file_handle)
+	if (s != APR_SUCCESS || !apr_file)
 	{		
+		pool->clearVolatileAPRPool() ;
+		
 		return 0;
 	}
 	else
 	{
-		apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, file_handle);
+		apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);		
 
-		apr_file_close(file_handle) ;
+		apr_file_close(apr_file) ;
+		pool->clearVolatileAPRPool() ;
 		
 		if (s == APR_SUCCESS)
 		{
 }
 
 //static
-bool LLAPRFile::makeDir(const std::string& dirname)
+bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
 {
 	apr_status_t s;
 
-	LLScopedVolatileAPRPool pool;
-	s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool);
+	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
+	s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool->getVolatileAPRPool());
+	pool->clearVolatileAPRPool() ;
 		
 	if (s != APR_SUCCESS)
 	{
 		ll_apr_warn_status(s);
-		LL_WARNS("APR") << " while attempting to make directory: " << dirname << LL_ENDL;
+		LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL;
 		return false;
 	}
 	return true;
 }
 
 //static
-bool LLAPRFile::removeDir(const std::string& dirname)
+bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
 {
 	apr_status_t s;
 
-	LLScopedVolatileAPRPool pool;
-	s = apr_file_remove(dirname.c_str(), pool);
+	pool = pool ? pool : LLAPRFile::sAPRFilePoolp ;
+	s = apr_file_remove(dirname.c_str(), pool->getVolatileAPRPool());
+	pool->clearVolatileAPRPool() ;
 	
 	if (s != APR_SUCCESS)
 	{

indra/llcommon/llapr.h

 #include "apr_atomic.h"
 #include "llstring.h"
 
+extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
+extern apr_thread_mutex_t* gCallStacksLogMutexp;
+
 struct apr_dso_handle_t;
-class LLAPRPool;
-class LLVolatileAPRPool;
+
+/** 
+ * @brief initialize the common apr constructs -- apr itself, the
+ * global pool, and a mutex.
+ */
+void LL_COMMON_API ll_init_apr();
+
+/** 
+ * @brief Cleanup those common apr constructs.
+ */
+void LL_COMMON_API ll_cleanup_apr();
+
+//
+//LL apr_pool
+//manage apr_pool_t, destroy allocated apr_pool in the destruction function.
+//
+class LL_COMMON_API LLAPRPool
+{
+public:
+	LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
+	virtual ~LLAPRPool() ;
+
+	virtual apr_pool_t* getAPRPool() ;
+	apr_status_t getStatus() {return mStatus ; }
+
+protected:
+	void releaseAPRPool() ;
+	void createAPRPool() ;
+
+protected:
+	apr_pool_t*  mPool ;              //pointing to an apr_pool
+	apr_pool_t*  mParent ;			  //parent pool
+	apr_size_t   mMaxSize ;           //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work.
+	apr_status_t mStatus ;            //status when creating the pool
+	BOOL         mReleasePoolFlag ;   //if set, mPool is destroyed when LLAPRPool is deleted. default value is true.
+};
+
+//
+//volatile LL apr_pool
+//which clears memory automatically.
+//so it can not hold static data or data after memory is cleared
+//
+class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool
+{
+public:
+	LLVolatileAPRPool(BOOL is_local = TRUE, apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
+	virtual ~LLVolatileAPRPool();
+
+	/*virtual*/ apr_pool_t* getAPRPool() ; //define this virtual function to avoid any mistakenly calling LLAPRPool::getAPRPool().
+	apr_pool_t* getVolatileAPRPool() ;	
+	void        clearVolatileAPRPool() ;
+
+	BOOL        isFull() ;
+	
+private:
+	S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
+	S32 mNumTotalRef ;  //number of total pointers pointing to the apr_pool since last creating.  
+
+	apr_thread_mutex_t *mMutexp;
+	apr_pool_t         *mMutexPool;
+} ;
 
 /** 
  * @class LLScopedLock
 	// make this non copyable since a copy closes the file
 private:
 	apr_file_t* mFile ;
-	LLVolatileAPRPool* mVolatileFilePoolp;	// (Thread local) APR pool currently in use.
-	LLAPRPool* mRegularFilePoolp;		// ...or a regular pool.
+	LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. 
 
 public:
-	enum access_t {
-		long_lived,		// Use a global pool for long-lived file accesses.
-		short_lived		// Use a volatile pool for short-lived file accesses.
-	};
-
 	LLAPRFile() ;
-	LLAPRFile(std::string const& filename, apr_int32_t flags, S32* sizep = NULL, access_t access_type = short_lived);
+	LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL);
 	~LLAPRFile() ;
-
-	apr_status_t open(const std::string& filename, apr_int32_t flags, access_t access_type, S32* sizep = NULL);
+	
+	apr_status_t open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL);
+	apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use gAPRPoolp.
 	apr_status_t close() ;
 
 	// Returns actual offset, -1 if seek fails
 	
 	apr_file_t* getFileHandle() {return mFile;}	
 
+private:
+	apr_pool_t* getAPRFilePool(apr_pool_t* pool) ;	
+	
 //
 //*******************************************************************************************************************************
 //static components
 //
+public:
+	static LLVolatileAPRPool *sAPRFilePoolp ; //a global apr_pool for APRFile, which is used only when local pool does not exist.
+
 private:
+	static apr_file_t* open(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags);
+	static apr_status_t close(apr_file_t* file, LLVolatileAPRPool* pool) ;
 	static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset);
 public:
 	// returns false if failure:
-	static bool remove(const std::string& filename);
-	static bool rename(const std::string& filename, const std::string& newname);
-	static bool isExist(const std::string& filename, apr_int32_t flags = APR_READ);
-	static S32 size(const std::string& filename);
-	static bool makeDir(const std::string& dirname);
-	static bool removeDir(const std::string& dirname);
+	static bool remove(const std::string& filename, LLVolatileAPRPool* pool = NULL);
+	static bool rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool = NULL);
+	static bool isExist(const std::string& filename, LLVolatileAPRPool* pool = NULL, apr_int32_t flags = APR_READ);
+	static S32 size(const std::string& filename, LLVolatileAPRPool* pool = NULL);
+	static bool makeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
+	static bool removeDir(const std::string& dirname, LLVolatileAPRPool* pool = NULL);
 
 	// Returns bytes read/written, 0 if read/write fails:
-	static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes);	
-	static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes); // offset<0 means append
+	static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);	
+	static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append
 //*******************************************************************************************************************************
 };
 
 void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
 void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle);
 
+extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
+
 #endif // LL_LLAPR_H

indra/llcommon/llaprpool.cpp

-/**
- * @file llaprpool.cpp
- *
- * $LicenseInfo:firstyear=2011&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$
- *
- * CHANGELOG
- *   and additional copyright holders.
- *
- *   04/04/2010
- *   - Initial version, written by Aleric Inglewood @ SL
- *
- *   10/11/2010
- *   - Added APR_HAS_THREADS #if's to allow creation and destruction
- *     of subpools by threads other than the parent pool owner.
- */
-
-#include "linden_common.h"
-
-#include "llerror.h"
-#include "llaprpool.h"
-#include "llthread.h"
-
-// Create a subpool from parent.
-void LLAPRPool::create(LLAPRPool& parent)
-{
-	llassert(!mPool);			// Must be non-initialized.
-	mParent = &parent;
-	if (!mParent)				// Using the default parameter?
-	{
-		// By default use the root pool of the current thread.
-		mParent = &LLThreadLocalData::tldata().mRootPool;
-	}
-	llassert(mParent->mPool);	// Parent must be initialized.
-#if APR_HAS_THREADS
-	// As per the documentation of APR (ie http://apr.apache.org/docs/apr/1.4/apr__pools_8h.html):
-	//
-	// Note that most operations on pools are not thread-safe: a single pool should only be
-	// accessed by a single thread at any given time. The one exception to this rule is creating
-	// a subpool of a given pool: one or more threads can safely create subpools at the same
-	// time that another thread accesses the parent pool.
-	//
-	// In other words, it's safe for any thread to create a (sub)pool, independent of who
-	// owns the parent pool.
-	mOwner = apr_os_thread_current();
-#else
-	mOwner = mParent->mOwner;
-	llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
-#endif
-	apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, mParent->mPool);
-	llassert_always(apr_pool_create_status == APR_SUCCESS);
-	llassert(mPool);			// Initialized.
-	apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null);
-}
-
-// Destroy the (sub)pool, if any.
-void LLAPRPool::destroy(void)
-{
-	// Only do anything if we are not already (being) destroyed.
-	if (mPool)
-	{
-#if !APR_HAS_THREADS
-		// If we are a root pool, then every thread may destruct us: in that case
-		// we have to assume that no other thread will use this pool concurrently,
-		// of course. Otherwise, if we are a subpool, only the thread that owns
-		// the parent may destruct us, since that is the pool that is still alive,
-		// possibly being used by others and being altered here.
-		llassert(!mParent || apr_os_thread_equal(mParent->mOwner, apr_os_thread_current()));
-#endif
-		apr_pool_t* pool = mPool;	// The use of apr_pool_t is OK here.
-									// Temporary store before destroying the pool.
-		mPool = NULL;				// Mark that we are BEING destructed.
-		apr_pool_cleanup_kill(pool, this, &s_plain_cleanup);
-		apr_pool_destroy(pool);
-	}
-}
-
-bool LLAPRPool::parent_is_being_destructed(void)
-{
-	return mParent && (!mParent->mPool || mParent->parent_is_being_destructed());
-}
-
-LLAPRInitialization::LLAPRInitialization(void)
-{
-	static bool apr_initialized = false;
-
-	if (!apr_initialized)
-	{
-		apr_initialize();
-	}
-
-	apr_initialized = true;
-}
-
-bool LLAPRRootPool::sCountInitialized = false;
-apr_uint32_t volatile LLAPRRootPool::sCount;
-
-apr_thread_mutex_t* gLogMutexp;
-apr_thread_mutex_t* gCallStacksLogMutexp;
-
-LLAPRRootPool::LLAPRRootPool(void) : LLAPRInitialization(), LLAPRPool(0)
-{
-	// sCountInitialized don't need locking because when we get here there is still only a single thread.
-	if (!sCountInitialized)
-	{
-		// Initialize the logging mutex
-		apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool);
-		apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool);
-
-		apr_status_t status = apr_atomic_init(mPool);
-		llassert_always(status == APR_SUCCESS);
-		apr_atomic_set32(&sCount, 1);	// Set to 1 to account for the global root pool.
-		sCountInitialized = true;
-
-		// Initialize thread-local APR pool support.
-		// Because this recursively calls LLAPRRootPool::LLAPRRootPool(void)
-		// it must be done last, so that sCount is already initialized.
-		LLThreadLocalData::init();
-	}
-	apr_atomic_inc32(&sCount);
-}
-
-LLAPRRootPool::~LLAPRRootPool()
-{
-	if (!apr_atomic_dec32(&sCount))
-	{
-		// The last pool was destructed. Cleanup remainder of APR.
-		LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
-
-		if (gLogMutexp)
-		{
-			// Clean up the logging mutex
-
-			// All other threads NEED to be done before we clean up APR, so this is okay.
-			apr_thread_mutex_destroy(gLogMutexp);
-			gLogMutexp = NULL;
-		}
-		if (gCallStacksLogMutexp)
-		{
-			// Clean up the logging mutex
-
-			// All other threads NEED to be done before we clean up APR, so this is okay.
-			apr_thread_mutex_destroy(gCallStacksLogMutexp);
-			gCallStacksLogMutexp = NULL;
-		}
-
-		// Must destroy ALL, and therefore this last LLAPRRootPool, before terminating APR.
-		static_cast<LLAPRRootPool*>(this)->destroy();
-
-		apr_terminate();
-	}
-}
-
-//static
-// Return a global root pool that is independent of LLThreadLocalData.
-// Normally you should NOT use this. Only use for early initialization
-// (before main) and deinitialization (after main).
-LLAPRRootPool& LLAPRRootPool::get(void)
-{
-  static LLAPRRootPool global_APRpool(0);
-  return global_APRpool;
-}
-
-void LLVolatileAPRPool::clearVolatileAPRPool()
-{
-	llassert_always(mNumActiveRef > 0);
-	if (--mNumActiveRef == 0)
-	{
-		if (isOld())
-		{
-			destroy();
-			mNumTotalRef = 0 ;
-		}
-		else
-		{
-			// This does not actually free the memory,
-			// it just allows the pool to re-use this memory for the next allocation.
-			clear();
-		}
-	}
-
-	// Paranoia check if the pool is jammed.
-	llassert(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
-}

indra/llcommon/llaprpool.h

-/**
- * @file llaprpool.h
- * @brief Implementation of LLAPRPool
- *
- * $LicenseInfo:firstyear=2011&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$
- *
- * CHANGELOG
- *   and additional copyright holders.
- *
- *   04/04/2010
- *   - Initial version, written by Aleric Inglewood @ SL
- *
- *   10/11/2010
- *   - Added APR_HAS_THREADS #if's to allow creation and destruction
- *     of subpools by threads other than the parent pool owner.
- *
- *   05/02/2011
- *   - Fixed compilation on windows: Suppress compile warning 4996
- *     and include <winsock2.h> before including <ws2tcpip.h>,
- *     by Merov Linden @ SL.
- */
-
-#ifndef LL_LLAPRPOOL_H
-#define LL_LLAPRPOOL_H
-
-#ifdef LL_WINDOWS
-#pragma warning(push)
-#pragma warning(disable:4996)
-#include <winsock2.h>
-#include <ws2tcpip.h>		// Needed before including apr_portable.h
-#pragma warning(pop)
-#endif
-
-#include "apr_portable.h"
-#include "apr_pools.h"
-#include "llerror.h"
-
-extern void ll_init_apr();
-
-/**
- * @brief A wrapper around the APR memory pool API.
- *
- * Usage of this class should be restricted to passing it to libapr-1 function calls that need it.
- *
- */
-class LL_COMMON_API LLAPRPool
-{
-protected:
-	//! Pointer to the underlaying pool. NULL if not initialized.
-	apr_pool_t* mPool;		// The use of apr_pool_t is OK here.
-							// This is the wrapped pointer that it is all about!
-	//! Pointer to the parent pool, if any. Only valid when mPool is non-zero.
-	LLAPRPool* mParent;
-	//! The thread that owns this memory pool. Only valid when mPool is non-zero.
-	apr_os_thread_t mOwner;
-
-public:
-	/// Construct an uninitialized (destructed) pool.
-	LLAPRPool(void) : mPool(NULL) { }
-
-	/// Construct a subpool from an existing pool.
-	/// This is not a copy-constructor, this class doesn't have one!
-	LLAPRPool(LLAPRPool& parent) : mPool(NULL) { create(parent); }
-
-	/// Destruct the memory pool (free all of its subpools and allocated memory).
-	~LLAPRPool() { destroy(); }
-
-protected:
-	/// Create a pool that is allocated from the Operating System. Only used by LLAPRRootPool.
-	LLAPRPool(int) : mPool(NULL), mParent(NULL), mOwner(apr_os_thread_current())
-	{
-		apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, NULL);
-		llassert_always(apr_pool_create_status == APR_SUCCESS);
-		llassert(mPool);
-		apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null);
-	}
-
-public:
-	/// Create a subpool from parent. May only be called for an uninitialized/destroyed pool.
-	/// The default parameter causes the root pool of the current thread to be used.
-	void create(LLAPRPool& parent = *static_cast<LLAPRPool*>(NULL));
-
-	/// Destroy the (sub)pool, if any.
-	void destroy(void);
-
-	// Use some safebool idiom (http://www.artima.com/cppsource/safebool.html) rather than operator bool.
-	typedef LLAPRPool* const LLAPRPool::* const bool_type;
-	/// Return true if the pool is initialized.
-	operator bool_type() const { return mPool ? &LLAPRPool::mParent : 0; }
-
-	/// Painful, but we have to either provide access to this, or wrap
-	/// every APR function call that needs an apr pool as argument.
-	/// NEVER destroy a pool that is returned by this function!
-	apr_pool_t* operator()(void) const		// The use of apr_pool_t is OK here.
-	  										// This is the accessor for passing the pool to libapr-1 functions.
-	{
-		llassert(mPool);
-		llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
-		return mPool;
-	}
-
-	/// Free all memory without destructing the pool.
-	void clear(void)
-	{
-		llassert(mPool);
-		llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
-		apr_pool_clear(mPool);
-	}
-
-// These methods would make this class 'complete' (as wrapper around the libapr
-// pool functions), but we don't use memory pools in the viewer (only when
-// we are forced to pass one to a libapr call), so don't define them in order
-// not to encourage people to use them.
-#if 0
-	void* palloc(size_t size)
-	{
-		llassert(mPool);
-		llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
-		return apr_palloc(mPool, size);
-	}
-	void* pcalloc(size_t size)
-	{
-		llassert(mPool);
-		llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
-		return apr_pcalloc(mPool, size);
-	}
-#endif
-
-private:
-	bool parent_is_being_destructed(void);
-	static apr_status_t s_plain_cleanup(void* userdata) { return static_cast<LLAPRPool*>(userdata)->plain_cleanup(); }
-
-	apr_status_t plain_cleanup(void)
-	{
-		if (mPool && 						// We are not being destructed,
-			parent_is_being_destructed())	// but our parent is.
-		  // This means the pool is being destructed recursively by libapr
-		  // because one of its parents is being destructed.
-		{
-			mPool = NULL;	// Stop destroy() from destructing the pool again.
-		}
-		return APR_SUCCESS;
-	}
-};
-
-class LLAPRInitialization
-{
-public:
-	LLAPRInitialization(void);
-};
-
-/**
- * @brief Root memory pool (allocates memory from the operating system).
- *
- * This class should only be used by LLThreadLocalData
- * (and LLMutexRootPool when APR_HAS_THREADS isn't defined).
- */
-class LL_COMMON_API LLAPRRootPool : public LLAPRInitialization, public LLAPRPool
-{
-private:
-	/// Construct a root memory pool. Should only be used by LLThreadLocalData and LLMutexRootPool.
-	friend class LLThreadLocalData;
-#if !APR_HAS_THREADS
-	friend class LLMutexRootPool;
-#endif
-	/// Construct a root memory pool.
-	/// Should only be used by LLThreadLocalData.
-	LLAPRRootPool(void);
-	~LLAPRRootPool();
-
-private:
-	// Keep track of how many root pools exist and when the last one is destructed.
-	static bool sCountInitialized;
-	static apr_uint32_t volatile sCount;
-
-public:
-	// Return a global root pool that is independent of LLThreadLocalData.
-	// Normally you should not use this. Only use for early initialization
-	// (before main) and deinitialization (after main).
-	static LLAPRRootPool& get(void);
-
-#if APR_POOL_DEBUG
-	void grab_ownership(void)
-	{
-		// You need a patched libapr to use this.
-		// See http://web.archiveorange.com/archive/v/5XO9y2zoxUOMt6Gmi1OI
-		apr_pool_owner_set(mPool);
-	}
-#endif
-
-private:
-	// Used for constructing the Special Global Root Pool (returned by LLAPRRootPool::get).
-	// It is the same as the default constructor but omits to increment sCount. As a result,
-	// we must be sure that at least one other LLAPRRootPool is created before termination
-	// of the application (which is the case: we create one LLAPRRootPool per thread).
-	LLAPRRootPool(int) : LLAPRInitialization(), LLAPRPool(0) { }
-};
-
-/** Volatile memory pool
- *
- * 'Volatile' APR memory pool which normally only clears memory,
- * and does not destroy the pool (the same pool is reused) for
- * greater efficiency. However, as a safe guard the apr pool
- * is destructed every FULL_VOLATILE_APR_POOL uses to allow
- * the system memory to be allocated more efficiently and not
- * get scattered through RAM.
- */
-class LL_COMMON_API LLVolatileAPRPool : protected LLAPRPool
-{
-public:
-	LLVolatileAPRPool(void) : mNumActiveRef(0), mNumTotalRef(0) { }
-
-	void clearVolatileAPRPool(void);
-
-	bool isOld(void) const { return mNumTotalRef > FULL_VOLATILE_APR_POOL; }
-	bool isUnused() const { return mNumActiveRef == 0; }
-
-private:
-	friend class LLScopedVolatileAPRPool;
-	friend class LLAPRFile;
-	apr_pool_t* getVolatileAPRPool(void)	// The use of apr_pool_t is OK here.
-	{
-		if (!mPool) create();
-		++mNumActiveRef;
-		++mNumTotalRef;
-		return LLAPRPool::operator()();
-	}
-
-private:
-	S32 mNumActiveRef;	// Number of active uses of the pool.
-	S32 mNumTotalRef;	// Number of total uses of the pool since last creation.
-
-	// Maximum number of references to LLVolatileAPRPool until the pool is recreated.
-	static S32 const FULL_VOLATILE_APR_POOL = 1024;
-};
-
-#endif // LL_LLAPRPOOL_H

indra/llcommon/llcommon.cpp

 #include "llthread.h"
 
 //static
+BOOL LLCommon::sAprInitialized = FALSE;
+
+//static
 void LLCommon::initClass()
 {
 	LLMemory::initClass();
+	if (!sAprInitialized)
+	{
+		ll_init_apr();
+		sAprInitialized = TRUE;
+	}
 	LLTimer::initClass();
 	LLThreadSafeRefCount::initThreadSafeRefCount();
 // 	LLWorkerThread::initClass();
 // 	LLWorkerThread::cleanupClass();
 	LLThreadSafeRefCount::cleanupThreadSafeRefCount();
 	LLTimer::cleanupClass();
+	if (sAprInitialized)
+	{
+		ll_cleanup_apr();
+		sAprInitialized = FALSE;
+	}
 	LLMemory::cleanupClass();
 }

indra/llcommon/llcommon.h

 public:
 	static void initClass();
 	static void cleanupClass();
+private:
+	static BOOL sAprInitialized;
 };
 
 #endif

indra/llcommon/llerror.cpp

 	
 */
 
-extern apr_thread_mutex_t* gLogMutexp;
-extern apr_thread_mutex_t* gCallStacksLogMutexp;
-
 namespace {
 	bool checkLevelMap(const LevelMap& map, const std::string& key,
 						LLError::ELevel& level)

indra/llcommon/llerror.h

 		Such computation is done iff the message will be logged.
 	*/
 
+
 #endif // LL_LLERROR_H

indra/llcommon/llfixedbuffer.cpp

 
 LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
 	: LLLineBuffer(),
-	  mMaxLines(max_lines)
+	  mMaxLines(max_lines),
+	  mMutex(NULL)
 {
 	mTimer.reset();
 }

indra/llcommon/llmemory.cpp

 	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 
 //--------------------------------------------------------------------
 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 ;
+		mMutexp = new LLMutex(NULL) ;
 	}
 
 	for(S32 i = 0 ; i < SUPER_ALLOCATION ; i++)
 				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 ;
 }
 
 	unlock() ;
 }
 
-void  LLPrivateMemoryPool::checkSize(U32 asked_size)
+bool LLPrivateMemoryPool::checkSize(U32 asked_size)
 {
 	if(mReservedPoolSize + asked_size > mMaxPoolSize)
 	{
 		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)
 			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) ;
 
 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())
 //--------------------------------------------------------------------
 LLPrivateMemoryPoolManager* LLPrivateMemoryPoolManager::sInstance = NULL ;
 
-LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled) 
+LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled, U32 max_pool_size) 
 {
 	mPoolList.resize(LLPrivateMemoryPool::MAX_TYPES) ;
 
 	}
 
 	mPrivatePoolEnabled = enabled ;
+
+	const U32 MAX_POOL_SIZE = 256 * 1024 * 1024 ; //256 MB
+	mMaxPrivatePoolSize = llmax(max_pool_size, MAX_POOL_SIZE) ;
 }
 
 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 
 
 	if(!mPoolList[type])
 	{
-		mPoolList[type] = new LLPrivateMemoryPool(type) ;
+		mPoolList[type] = new LLPrivateMemoryPool(type, mMaxPrivatePoolSize) ;
 	}
 
 	return mPoolList[type] ;

indra/llcommon/llmemory.h

 	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() ;
 	} ;
 
 private:
-	LLPrivateMemoryPool(S32 type) ;
+	LLPrivateMemoryPool(S32 type, U32 max_pool_size) ;
 	~LLPrivateMemoryPool() ;
 
 	char *allocate(U32 size) ;
 	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) ;
 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) ;
 	static LLPrivateMemoryPoolManager* sInstance ;
 	std::vector<LLPrivateMemoryPool*> mPoolList ;
 	BOOL mPrivatePoolEnabled;
+	U32  mMaxPrivatePoolSize;
 
 public:
 	//debug and statistics info.

indra/llcommon/llqueuedthread.cpp

 //============================================================================
 
 // 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),
 {
 	if (mThreaded)
 	{
+		if(should_pause)
+		{
+			pause() ; //call this before start the thread.
+		}
+
 		start();
 	}
 }

indra/llcommon/llqueuedthread.h

 	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();
 	

indra/llcommon/llscopedvolatileaprpool.h

-/**
- * @file llscopedvolatileaprpool.h
- * @brief Implementation of LLScopedVolatileAPRPool
- *
- * $LicenseInfo:firstyear=2010&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$
- */
-
-#ifndef LL_LLSCOPEDVOLATILEAPRPOOL_H
-#define LL_LLSCOPEDVOLATILEAPRPOOL_H
-
-#include "llthread.h"
-
-/** Scoped volatile memory pool.
- *
- * As the LLVolatileAPRPool should never keep allocations very
- * long, its most common use is for allocations with a lifetime
- * equal to it's scope.
- *
- * This is a convenience class that makes just a little easier to type.
- */
-class LL_COMMON_API LLScopedVolatileAPRPool
-{
-private:
-	LLVolatileAPRPool& mPool;
-	apr_pool_t* mScopedAPRpool;		// The use of apr_pool_t is OK here.
-public:
-	LLScopedVolatileAPRPool() : mPool(LLThreadLocalData::tldata().mVolatileAPRPool), mScopedAPRpool(mPool.getVolatileAPRPool()) { }
-	~LLScopedVolatileAPRPool() { mPool.clearVolatileAPRPool(); }
-	//! @attention Only use this to pass the underlaying pointer to a libapr-1 function that requires it.
-	operator apr_pool_t*() const { return mScopedAPRpool; }		// The use of apr_pool_t is OK here.
-};
-
-#endif

indra/llcommon/llsdserialize_xml.cpp

 	return count;
 }
 
-LLFastTimer::DeclareTimer FTM_SD_PARSE_READ_STREAM("LLSD Read Stream");
 S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data)
 {
 	XML_Status status;
 		{
 			break;
 		}
-		{ LLFastTimer _(FTM_SD_PARSE_READ_STREAM);
+		{
 		
 			count = get_till_eol(input, (char *)buffer, BUFFER_SIZE);
 			if (!count)

indra/llcommon/llthread.cpp

 #include <sched.h>
 #endif
 
-#if !LL_DARWIN
-U32 ll_thread_local local_thread_ID = 0;
-#endif 
-
-U32 LLThread::sIDIter = 0;
-
 //----------------------------------------------------------------------------
 // Usage:
 // void run_func(LLThread* thread)
 // 
 //----------------------------------------------------------------------------
 
+#if !LL_DARWIN
+U32 ll_thread_local sThreadID = 0;
+#endif 
+
+U32 LLThread::sIDIter = 0;
+
 LL_COMMON_API void assert_main_thread()
 {
 	static U32 s_thread_id = LLThread::currentID();
 	LLThread *threadp = (LLThread *)datap;
 
 #if !LL_DARWIN
-	local_thread_ID = threadp->mID;
+	sThreadID = threadp->mID;
 #endif
 
-	// Create a thread local data.
-	LLThreadLocalData::create(threadp);
-
 	// Run the user supplied function
 	threadp->run();
 
 }
 
 
-LLThread::LLThread(std::string const& name) :
-	mPaused(false),
+LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
+	mPaused(FALSE),
 	mName(name),
 	mAPRThreadp(NULL),
-	mStatus(STOPPED),
-	mThreadLocalData(NULL)
+	mStatus(STOPPED)
 {
-	mID = ++sIDIter; //flaw: assume this is called only in the main thread!
+	mID = ++sIDIter;
 
-	mRunCondition = new LLCondition;
+	// Thread creation probably CAN be paranoid about APR being initialized, if necessary
+	if (poolp)
+	{
+		mIsLocalPool = FALSE;
+		mAPRPoolp = poolp;
+	}
+	else
+	{
+		mIsLocalPool = TRUE;
+		apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
+	}
+	mRunCondition = new LLCondition(mAPRPoolp);
+
+	mLocalAPRFilePoolp = NULL ;
 }
 
 
 LLThread::~LLThread()
 {
 	shutdown();
+
+	if(mLocalAPRFilePoolp)
+	{
+		delete mLocalAPRFilePoolp ;
+		mLocalAPRFilePoolp = NULL ;
+	}
 }
 
 void LLThread::shutdown()
 		if (!isStopped())
 		{
 			// This thread just wouldn't stop, even though we gave it time
-			//llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl;
+			//llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
 			// Put a stake in its heart.
 			apr_thread_exit(mAPRThreadp, -1);
 			return;
 
 	delete mRunCondition;
 	mRunCondition = 0;
+	
+	if (mIsLocalPool && mAPRPoolp)
+	{
+		apr_pool_destroy(mAPRPoolp);
+		mAPRPoolp = 0;
+	}
 }
 
+
 void LLThread::start()
 {
 	llassert(isStopped());
 	mStatus = RUNNING;
 
 	apr_status_t status =
-		apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool());
+		apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
 	
 	if(status == APR_SUCCESS)
 	{	
 	if (!mPaused)
 	{
 		// this will cause the thread to stop execution as soon as checkPause() is called
-		mPaused = true;		// Does not need to be atomic since this is only set/unset from the main thread
+		mPaused = 1;		// Does not need to be atomic since this is only set/unset from the main thread
 	}	
 }
 
 {
 	if (mPaused)
 	{
-		mPaused = false;
+		mPaused = 0;
 	}