diff options
Diffstat (limited to 'indra/llcommon/llapr.cpp')
-rw-r--r-- | indra/llcommon/llapr.cpp | 1494 |
1 files changed, 747 insertions, 747 deletions
diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 0aa68f28cb..b085f8f5dc 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -1,747 +1,747 @@ -/**
- * @file llapr.cpp
- * @author Phoenix
- * @date 2004-11-28
- * @brief Helper functions for using the apache portable runtime library.
- *
- * $LicenseInfo:firstyear=2004&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-#include "llapr.h"
-#include "llmutex.h"
-#include "apr_dso.h"
-
-apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
-LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
-
-const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
-
-bool gAPRInitialized = false;
-
-int abortfunc(int retcode)
-{
- LL_WARNS("APR") << "Allocation failure in apr pool with code " << (S32)retcode << LL_ENDL;
- return 0;
-}
-
-void ll_init_apr()
-{
- // Initialize APR and create the global pool
- apr_initialize();
-
- if (!gAPRPoolp)
- {
- apr_pool_create_ex(&gAPRPoolp, NULL, abortfunc, NULL);
- }
-
- if(!LLAPRFile::sAPRFilePoolp)
- {
- LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(false) ;
- }
-
- gAPRInitialized = true;
-}
-
-
-bool ll_apr_is_initialized()
-{
- return gAPRInitialized;
-}
-
-void ll_cleanup_apr()
-{
- gAPRInitialized = false;
-
- LL_DEBUGS("APR") << "Cleaning up APR" << LL_ENDL;
-
- 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)
-{
- //create mutex
- if(!is_local) //not a local apr_pool, that is: shared by multiple threads.
- {
- mMutexp.reset(new std::mutex());
- }
-}
-
-LLVolatileAPRPool::~LLVolatileAPRPool()
-{
- //delete mutex
- mMutexp.reset();
-}
-
-//
-//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.get()) ;
-
- mNumTotalRef++ ;
- mNumActiveRef++ ;
-
- if(!mPool)
- {
- createAPRPool() ;
- }
-
- return mPool ;
-}
-
-void LLVolatileAPRPool::clearVolatileAPRPool()
-{
- LLScopedLock lock(mMutexp.get());
-
- 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) ;
- }
-
- llassert(mNumTotalRef <= (FULL_VOLATILE_APR_POOL << 2)) ;
-}
-
-bool LLVolatileAPRPool::isFull()
-{
- return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
-}
-
-//---------------------------------------------------------------------
-
-bool _ll_apr_warn_status(apr_status_t status, const char* file, int line)
-{
- if(APR_SUCCESS == status) return false;
-#if !LL_LINUX
- char buf[MAX_STRING]; /* Flawfinder: ignore */
- apr_strerror(status, buf, sizeof(buf));
- LL_WARNS("APR") << "APR: " << file << ":" << line << " " << buf << LL_ENDL;
-#endif
- return true;
-}
-
-void _ll_apr_assert_status(apr_status_t status, const char* file, int line)
-{
- llassert(! _ll_apr_warn_status(status, file, line));
-}
-
-//---------------------------------------------------------------------
-//
-// Scope based pool access
-//
-//---------------------------------------------------------------------
-
-class LLAPRFilePoolScope
-{
-public:
- LLAPRFilePoolScope() : pPool(NULL), mInitialized(false) {}
- LLAPRFilePoolScope(LLVolatileAPRPool* poolp) : mInitialized(false)
- {
- setFilePool(poolp);
- }
- ~LLAPRFilePoolScope()
- {
- reset();
- }
- apr_pool_t* getVolatileAPRPool(LLVolatileAPRPool* poolp = NULL)
- {
- if (!pPool)
- {
- setFilePool(poolp);
- }
- if (mInitialized)
- {
- // We need one clear per one get
- // At the moment no need to support multiple calls
- LL_ERRS() << "LLAPRFilePoolScope is not supposed to be initialized twice" << LL_ENDL;
- }
- mInitialized = true;
- return pPool->getVolatileAPRPool();
- }
- void reset()
- {
- if (mInitialized)
- {
- pPool->clearVolatileAPRPool();
- }
- }
-
-private:
- void setFilePool(LLVolatileAPRPool* poolp = NULL)
- {
- if (poolp)
- {
- pPool = poolp;
- }
- else
- {
- pPool = LLAPRFile::sAPRFilePoolp;
- }
- }
-
- LLVolatileAPRPool *pPool;
- bool mInitialized;
-};
-
-//---------------------------------------------------------------------
-//
-// LLAPRFile functions
-//
-LLAPRFile::LLAPRFile()
- : mFile(NULL),
- mCurrentFilePoolp(NULL)
-{
-}
-
-LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool)
- : mFile(NULL),
- mCurrentFilePoolp(NULL)
-{
- open(filename, flags, pool);
-}
-
-LLAPRFile::~LLAPRFile()
-{
- close() ;
-}
-
-apr_status_t LLAPRFile::close()
-{
- apr_status_t ret = APR_SUCCESS ;
- if(mFile)
- {
- ret = apr_file_close(mFile);
- mFile = NULL ;
- }
-
- if(mCurrentFilePoolp)
- {
- mCurrentFilePoolp->clearVolatileAPRPool() ;
- mCurrentFilePoolp = NULL ;
- }
-
- return ret ;
-}
-
-apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep)
-{
- apr_status_t s ;
-
- //check if already open some file
- llassert_always(!mFile) ;
- llassert_always(!mCurrentFilePoolp) ;
-
- mCurrentFilePoolp = pool ? pool : sAPRFilePoolp;
- apr_pool_t* apr_pool = mCurrentFilePoolp->getVolatileAPRPool(); //paired with clear in close()
- s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);
-
- if (s != APR_SUCCESS || !mFile)
- {
- mFile = NULL ;
-
- if (sizep)
- {
- *sizep = 0;
- }
- }
- else if (sizep)
- {
- S32 file_size = 0;
- apr_off_t offset = 0;
- if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS)
- {
- llassert_always(offset <= 0x7fffffff);
- file_size = (S32)offset;
- offset = 0;
- apr_file_seek(mFile, APR_SET, &offset);
- }
- *sizep = file_size;
- }
-
- if (!mFile)
- {
- // It will clean pool
- 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;
-}
-
-// File I/O
-S32 LLAPRFile::read(void *buf, S32 nbytes)
-{
- if(!mFile)
- {
- LL_WARNS() << "apr mFile is removed by somebody else. Can not read." << LL_ENDL ;
- return 0;
- }
-
- apr_size_t sz = nbytes;
- apr_status_t s = apr_file_read(mFile, buf, &sz);
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- return 0;
- }
- else
- {
- llassert_always(sz <= 0x7fffffff);
- return (S32)sz;
- }
-}
-
-S32 LLAPRFile::write(const void *buf, S32 nbytes)
-{
- if(!mFile)
- {
- LL_WARNS() << "apr mFile is removed by somebody else. Can not write." << LL_ENDL ;
- return 0;
- }
-
- apr_size_t sz = nbytes;
- apr_status_t s = apr_file_write(mFile, buf, &sz);
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- return 0;
- }
- else
- {
- llassert_always(sz <= 0x7fffffff);
- return (S32)sz;
- }
-}
-
-S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
-{
- return LLAPRFile::seek(mFile, where, offset) ;
-}
-
-//
-//*******************************************************************************************************************************
-//static components of LLAPRFile
-//
-
-//static
-apr_status_t LLAPRFile::close(apr_file_t* file_handle)
-{
- apr_status_t ret = APR_SUCCESS ;
- if(file_handle)
- {
- ret = apr_file_close(file_handle);
- file_handle = NULL ;
- }
-
- return ret ;
-}
-
-//static
-apr_file_t* LLAPRFile::open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags)
-{
- apr_status_t s;
- apr_file_t* file_handle ;
-
-
- s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool);
- 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) ;
- return NULL;
- }
-
- return file_handle ;
-}
-
-//static
-S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
-{
- if(!file_handle)
- {
- return -1 ;
- }
-
- apr_status_t s;
- apr_off_t apr_offset;
- if (offset >= 0)
- {
- apr_offset = (apr_off_t)offset;
- s = apr_file_seek(file_handle, where, &apr_offset);
- }
- else
- {
- apr_offset = 0;
- s = apr_file_seek(file_handle, APR_END, &apr_offset);
- }
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- return -1;
- }
- else
- {
- llassert_always(apr_offset <= 0x7fffffff);
- return (S32)apr_offset;
- }
-}
-
-//static
-S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
-{
- LL_PROFILE_ZONE_SCOPED;
- //*****************************************
- LLAPRFilePoolScope scope(pool);
- apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY);
- //*****************************************
- if (!file_handle)
- {
- return 0;
- }
-
- llassert(offset >= 0);
-
- if (offset > 0)
- offset = LLAPRFile::seek(file_handle, APR_SET, offset);
-
- apr_size_t bytes_read;
- if (offset < 0)
- {
- bytes_read = 0;
- }
- else
- {
- bytes_read = nbytes ;
- apr_status_t s = apr_file_read(file_handle, buf, &bytes_read);
- if (s != APR_SUCCESS)
- {
- LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL;
- ll_apr_warn_status(s);
- bytes_read = 0;
- }
- else
- {
- llassert_always(bytes_read <= 0x7fffffff);
- }
- }
-
- //*****************************************
- close(file_handle) ;
- //*****************************************
- return (S32)bytes_read;
-}
-
-//static
-S32 LLAPRFile::writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool)
-{
- LL_PROFILE_ZONE_SCOPED;
- apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY;
- if (offset < 0)
- {
- flags |= APR_APPEND;
- offset = 0;
- }
-
- //*****************************************
- LLAPRFilePoolScope scope(pool);
- apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), flags);
- //*****************************************
- if (!file_handle)
- {
- return 0;
- }
-
- if (offset > 0)
- {
- offset = LLAPRFile::seek(file_handle, APR_SET, offset);
- }
-
- apr_size_t bytes_written;
- if (offset < 0)
- {
- bytes_written = 0;
- }
- else
- {
- bytes_written = nbytes ;
- apr_status_t s = apr_file_write(file_handle, buf, &bytes_written);
- if (s != APR_SUCCESS)
- {
- LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL;
- ll_apr_warn_status(s);
- bytes_written = 0;
- }
- else
- {
- llassert_always(bytes_written <= 0x7fffffff);
- }
- }
-
- //*****************************************
- LLAPRFile::close(file_handle);
- //*****************************************
-
- return (S32)bytes_written;
-}
-
-//static
-bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool)
-{
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_remove(filename.c_str(), scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL;
- return false;
- }
- return true;
-}
-
-//static
-bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool)
-{
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_rename(filename.c_str(), newname.c_str(), scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL;
- return false;
- }
- return true;
-}
-
-//static
-bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags)
-{
- apr_file_t* apr_file;
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS || !apr_file)
- {
- return false;
- }
- else
- {
- apr_file_close(apr_file) ;
- return true;
- }
-}
-
-//static
-S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool)
-{
- apr_file_t* apr_file;
- apr_finfo_t info;
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS || !apr_file)
- {
- return 0;
- }
- else
- {
- apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file);
-
- apr_file_close(apr_file) ;
-
- if (s == APR_SUCCESS)
- {
- return (S32)info.size;
- }
- else
- {
- return 0;
- }
- }
-}
-
-//static
-bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool)
-{
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL;
- return false;
- }
- return true;
-}
-
-//static
-bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool)
-{
- apr_status_t s;
-
- LLAPRFilePoolScope scope(pool);
- s = apr_file_remove(dirname.c_str(), scope.getVolatileAPRPool());
-
- if (s != APR_SUCCESS)
- {
- ll_apr_warn_status(s);
- LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL;
- return false;
- }
- return true;
-}
-//
-//end of static components of LLAPRFile
-//*******************************************************************************************************************************
-//
+/** + * @file llapr.cpp + * @author Phoenix + * @date 2004-11-28 + * @brief Helper functions for using the apache portable runtime library. + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llapr.h" +#include "llmutex.h" +#include "apr_dso.h" + +apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool +LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool. + +const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool + +bool gAPRInitialized = false; + +int abortfunc(int retcode) +{ + LL_WARNS("APR") << "Allocation failure in apr pool with code " << (S32)retcode << LL_ENDL; + return 0; +} + +void ll_init_apr() +{ + // Initialize APR and create the global pool + apr_initialize(); + + if (!gAPRPoolp) + { + apr_pool_create_ex(&gAPRPoolp, NULL, abortfunc, NULL); + } + + if(!LLAPRFile::sAPRFilePoolp) + { + LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(false) ; + } + + gAPRInitialized = true; +} + + +bool ll_apr_is_initialized() +{ + return gAPRInitialized; +} + +void ll_cleanup_apr() +{ + gAPRInitialized = false; + + LL_DEBUGS("APR") << "Cleaning up APR" << LL_ENDL; + + 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) +{ + //create mutex + if(!is_local) //not a local apr_pool, that is: shared by multiple threads. + { + mMutexp.reset(new std::mutex()); + } +} + +LLVolatileAPRPool::~LLVolatileAPRPool() +{ + //delete mutex + mMutexp.reset(); +} + +// +//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.get()) ; + + mNumTotalRef++ ; + mNumActiveRef++ ; + + if(!mPool) + { + createAPRPool() ; + } + + return mPool ; +} + +void LLVolatileAPRPool::clearVolatileAPRPool() +{ + LLScopedLock lock(mMutexp.get()); + + 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) ; + } + + llassert(mNumTotalRef <= (FULL_VOLATILE_APR_POOL << 2)) ; +} + +bool LLVolatileAPRPool::isFull() +{ + return mNumTotalRef > FULL_VOLATILE_APR_POOL ; +} + +//--------------------------------------------------------------------- + +bool _ll_apr_warn_status(apr_status_t status, const char* file, int line) +{ + if(APR_SUCCESS == status) return false; +#if !LL_LINUX + char buf[MAX_STRING]; /* Flawfinder: ignore */ + apr_strerror(status, buf, sizeof(buf)); + LL_WARNS("APR") << "APR: " << file << ":" << line << " " << buf << LL_ENDL; +#endif + return true; +} + +void _ll_apr_assert_status(apr_status_t status, const char* file, int line) +{ + llassert(! _ll_apr_warn_status(status, file, line)); +} + +//--------------------------------------------------------------------- +// +// Scope based pool access +// +//--------------------------------------------------------------------- + +class LLAPRFilePoolScope +{ +public: + LLAPRFilePoolScope() : pPool(NULL), mInitialized(false) {} + LLAPRFilePoolScope(LLVolatileAPRPool* poolp) : mInitialized(false) + { + setFilePool(poolp); + } + ~LLAPRFilePoolScope() + { + reset(); + } + apr_pool_t* getVolatileAPRPool(LLVolatileAPRPool* poolp = NULL) + { + if (!pPool) + { + setFilePool(poolp); + } + if (mInitialized) + { + // We need one clear per one get + // At the moment no need to support multiple calls + LL_ERRS() << "LLAPRFilePoolScope is not supposed to be initialized twice" << LL_ENDL; + } + mInitialized = true; + return pPool->getVolatileAPRPool(); + } + void reset() + { + if (mInitialized) + { + pPool->clearVolatileAPRPool(); + } + } + +private: + void setFilePool(LLVolatileAPRPool* poolp = NULL) + { + if (poolp) + { + pPool = poolp; + } + else + { + pPool = LLAPRFile::sAPRFilePoolp; + } + } + + LLVolatileAPRPool *pPool; + bool mInitialized; +}; + +//--------------------------------------------------------------------- +// +// LLAPRFile functions +// +LLAPRFile::LLAPRFile() + : mFile(NULL), + mCurrentFilePoolp(NULL) +{ +} + +LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool) + : mFile(NULL), + mCurrentFilePoolp(NULL) +{ + open(filename, flags, pool); +} + +LLAPRFile::~LLAPRFile() +{ + close() ; +} + +apr_status_t LLAPRFile::close() +{ + apr_status_t ret = APR_SUCCESS ; + if(mFile) + { + ret = apr_file_close(mFile); + mFile = NULL ; + } + + if(mCurrentFilePoolp) + { + mCurrentFilePoolp->clearVolatileAPRPool() ; + mCurrentFilePoolp = NULL ; + } + + return ret ; +} + +apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep) +{ + apr_status_t s ; + + //check if already open some file + llassert_always(!mFile) ; + llassert_always(!mCurrentFilePoolp) ; + + mCurrentFilePoolp = pool ? pool : sAPRFilePoolp; + apr_pool_t* apr_pool = mCurrentFilePoolp->getVolatileAPRPool(); //paired with clear in close() + s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool); + + if (s != APR_SUCCESS || !mFile) + { + mFile = NULL ; + + if (sizep) + { + *sizep = 0; + } + } + else if (sizep) + { + S32 file_size = 0; + apr_off_t offset = 0; + if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS) + { + llassert_always(offset <= 0x7fffffff); + file_size = (S32)offset; + offset = 0; + apr_file_seek(mFile, APR_SET, &offset); + } + *sizep = file_size; + } + + if (!mFile) + { + // It will clean pool + 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; +} + +// File I/O +S32 LLAPRFile::read(void *buf, S32 nbytes) +{ + if(!mFile) + { + LL_WARNS() << "apr mFile is removed by somebody else. Can not read." << LL_ENDL ; + return 0; + } + + apr_size_t sz = nbytes; + apr_status_t s = apr_file_read(mFile, buf, &sz); + if (s != APR_SUCCESS) + { + ll_apr_warn_status(s); + return 0; + } + else + { + llassert_always(sz <= 0x7fffffff); + return (S32)sz; + } +} + +S32 LLAPRFile::write(const void *buf, S32 nbytes) +{ + if(!mFile) + { + LL_WARNS() << "apr mFile is removed by somebody else. Can not write." << LL_ENDL ; + return 0; + } + + apr_size_t sz = nbytes; + apr_status_t s = apr_file_write(mFile, buf, &sz); + if (s != APR_SUCCESS) + { + ll_apr_warn_status(s); + return 0; + } + else + { + llassert_always(sz <= 0x7fffffff); + return (S32)sz; + } +} + +S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset) +{ + return LLAPRFile::seek(mFile, where, offset) ; +} + +// +//******************************************************************************************************************************* +//static components of LLAPRFile +// + +//static +apr_status_t LLAPRFile::close(apr_file_t* file_handle) +{ + apr_status_t ret = APR_SUCCESS ; + if(file_handle) + { + ret = apr_file_close(file_handle); + file_handle = NULL ; + } + + return ret ; +} + +//static +apr_file_t* LLAPRFile::open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags) +{ + apr_status_t s; + apr_file_t* file_handle ; + + + s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, apr_pool); + 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) ; + return NULL; + } + + return file_handle ; +} + +//static +S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) +{ + if(!file_handle) + { + return -1 ; + } + + apr_status_t s; + apr_off_t apr_offset; + if (offset >= 0) + { + apr_offset = (apr_off_t)offset; + s = apr_file_seek(file_handle, where, &apr_offset); + } + else + { + apr_offset = 0; + s = apr_file_seek(file_handle, APR_END, &apr_offset); + } + if (s != APR_SUCCESS) + { + ll_apr_warn_status(s); + return -1; + } + else + { + llassert_always(apr_offset <= 0x7fffffff); + return (S32)apr_offset; + } +} + +//static +S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) +{ + LL_PROFILE_ZONE_SCOPED; + //***************************************** + LLAPRFilePoolScope scope(pool); + apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), APR_READ|APR_BINARY); + //***************************************** + if (!file_handle) + { + return 0; + } + + llassert(offset >= 0); + + if (offset > 0) + offset = LLAPRFile::seek(file_handle, APR_SET, offset); + + apr_size_t bytes_read; + if (offset < 0) + { + bytes_read = 0; + } + else + { + bytes_read = nbytes ; + apr_status_t s = apr_file_read(file_handle, buf, &bytes_read); + if (s != APR_SUCCESS) + { + LL_WARNS("APR") << " Attempting to read filename: " << filename << LL_ENDL; + ll_apr_warn_status(s); + bytes_read = 0; + } + else + { + llassert_always(bytes_read <= 0x7fffffff); + } + } + + //***************************************** + close(file_handle) ; + //***************************************** + return (S32)bytes_read; +} + +//static +S32 LLAPRFile::writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) +{ + LL_PROFILE_ZONE_SCOPED; + apr_int32_t flags = APR_CREATE|APR_WRITE|APR_BINARY; + if (offset < 0) + { + flags |= APR_APPEND; + offset = 0; + } + + //***************************************** + LLAPRFilePoolScope scope(pool); + apr_file_t* file_handle = open(filename, scope.getVolatileAPRPool(), flags); + //***************************************** + if (!file_handle) + { + return 0; + } + + if (offset > 0) + { + offset = LLAPRFile::seek(file_handle, APR_SET, offset); + } + + apr_size_t bytes_written; + if (offset < 0) + { + bytes_written = 0; + } + else + { + bytes_written = nbytes ; + apr_status_t s = apr_file_write(file_handle, buf, &bytes_written); + if (s != APR_SUCCESS) + { + LL_WARNS("APR") << " Attempting to write filename: " << filename << LL_ENDL; + ll_apr_warn_status(s); + bytes_written = 0; + } + else + { + llassert_always(bytes_written <= 0x7fffffff); + } + } + + //***************************************** + LLAPRFile::close(file_handle); + //***************************************** + + return (S32)bytes_written; +} + +//static +bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool) +{ + apr_status_t s; + + LLAPRFilePoolScope scope(pool); + s = apr_file_remove(filename.c_str(), scope.getVolatileAPRPool()); + + if (s != APR_SUCCESS) + { + ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to remove filename: " << filename << LL_ENDL; + return false; + } + return true; +} + +//static +bool LLAPRFile::rename(const std::string& filename, const std::string& newname, LLVolatileAPRPool* pool) +{ + apr_status_t s; + + LLAPRFilePoolScope scope(pool); + s = apr_file_rename(filename.c_str(), newname.c_str(), scope.getVolatileAPRPool()); + + if (s != APR_SUCCESS) + { + ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to rename filename: " << filename << LL_ENDL; + return false; + } + return true; +} + +//static +bool LLAPRFile::isExist(const std::string& filename, LLVolatileAPRPool* pool, apr_int32_t flags) +{ + apr_file_t* apr_file; + apr_status_t s; + + LLAPRFilePoolScope scope(pool); + s = apr_file_open(&apr_file, filename.c_str(), flags, APR_OS_DEFAULT, scope.getVolatileAPRPool()); + + if (s != APR_SUCCESS || !apr_file) + { + return false; + } + else + { + apr_file_close(apr_file) ; + return true; + } +} + +//static +S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool) +{ + apr_file_t* apr_file; + apr_finfo_t info; + apr_status_t s; + + LLAPRFilePoolScope scope(pool); + s = apr_file_open(&apr_file, filename.c_str(), APR_READ, APR_OS_DEFAULT, scope.getVolatileAPRPool()); + + if (s != APR_SUCCESS || !apr_file) + { + return 0; + } + else + { + apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, apr_file); + + apr_file_close(apr_file) ; + + if (s == APR_SUCCESS) + { + return (S32)info.size; + } + else + { + return 0; + } + } +} + +//static +bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool) +{ + apr_status_t s; + + LLAPRFilePoolScope scope(pool); + s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, scope.getVolatileAPRPool()); + + if (s != APR_SUCCESS) + { + ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to make directory: " << dirname << LL_ENDL; + return false; + } + return true; +} + +//static +bool LLAPRFile::removeDir(const std::string& dirname, LLVolatileAPRPool* pool) +{ + apr_status_t s; + + LLAPRFilePoolScope scope(pool); + s = apr_file_remove(dirname.c_str(), scope.getVolatileAPRPool()); + + if (s != APR_SUCCESS) + { + ll_apr_warn_status(s); + LL_WARNS("APR") << " Attempting to remove directory: " << dirname << LL_ENDL; + return false; + } + return true; +} +// +//end of static components of LLAPRFile +//******************************************************************************************************************************* +// |