diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index 01763c49aa..8f131dfc9f 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -307,17 +307,46 @@ class LLAPRFilePoolScope // LLAPRFile::LLAPRFile() : mFile(NULL), + mMMapFile(NULL), mCurrentFilePoolp(NULL) { } LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool) : mFile(NULL), + mMMapFile(NULL), mCurrentFilePoolp(NULL) { open(filename, flags, pool); } +// Create a memory map file file pointer +LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, LLVolatileAPRPool* pool) + : mFile(NULL), + mMMapFile(NULL), + mCurrentFilePoolp(NULL) +{ + openMemoryMap(filename, flags, mmap_flags, pool); +} + +// Create a 64 bit memory map file pointer and initalize it. +LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, S64 init_file_size, bool zero_out, LLVolatileAPRPool* pool) + : mFile(NULL), + mMMapFile(NULL), + mCurrentFilePoolp(NULL) +{ + openMemoryMap64(filename, flags, mmap_flags, init_file_size, zero_out, pool); +} + +// Create a 32 bit memory map file pointer and initalize it. +LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, S32 init_file_size, bool zero_out, LLVolatileAPRPool* pool) + : mFile(NULL), + mMMapFile(NULL), + mCurrentFilePoolp(NULL) +{ + openMemoryMap(filename, flags, mmap_flags, init_file_size, zero_out, pool); +} + LLAPRFile::~LLAPRFile() { close() ; @@ -326,6 +355,17 @@ LLAPRFile::~LLAPRFile() apr_status_t LLAPRFile::close() { apr_status_t ret = APR_SUCCESS ; + // Check if memory map file could be deleted, defaults to success so if not used, does not affect return value + apr_status_t mmap_ret = APR_SUCCESS; + + // If the memory map file is used and exists + if (mMMapFile) + { + // Try to delete the memory map first + mmap_ret = apr_mmap_delete(mMMapFile); + mMMapFile = NULL; + } + if(mFile) { ret = apr_file_close(mFile); @@ -338,7 +378,36 @@ apr_status_t LLAPRFile::close() mCurrentFilePoolp = NULL ; } - return ret ; + // If both operations failed, log both errors + if (ret != APR_SUCCESS && mmap_ret != APR_SUCCESS) + { + LL_WARNS("APR") << "Both apr_file_close and apr_mmap_delete failed: " + << "apr_file_close returned " << (S32)ret << ", " + << "apr_mmap_delete returned " << (S32)mmap_ret << LL_ENDL; + + // Return the file close error code by convention + return ret; + } + + // If only one failed, return the error code + if (ret != APR_SUCCESS) + { + LL_WARNS("APR") << "apr_file_close failed: " + << "apr_file_close returned " << (S32)ret << LL_ENDL; + + return ret; + } + + if (mmap_ret != APR_SUCCESS) + { + LL_WARNS("APR") << "apr_mmap_delete failed: " + << "apr_mmap_delete returned " << (S32)mmap_ret << LL_ENDL; + + return mmap_ret; + } + + // Both succeeded + return APR_SUCCESS; } apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S32* sizep) @@ -355,6 +424,7 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLV if (s != APR_SUCCESS || !mFile) { + LL_WARNS() << "Could not open file: " << filename << LL_ENDL; mFile = NULL ; if (sizep) @@ -385,6 +455,274 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, LLV return s ; } +apr_status_t LLAPRFile::open64(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool, S64* 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) + { + LL_WARNS() << "Could not open file: " << filename << LL_ENDL; + mFile = NULL; + + if (sizep) + { + *sizep = 0; + } + } + else if (sizep) + { + S64 file_size = 0; + apr_off_t offset = 0; + if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS) + { + llassert_always(offset <= 0x7fffffffffffffff); + file_size = offset; + offset = 0; + apr_file_seek(mFile, APR_SET, &offset); + } + *sizep = file_size; + } + + if (!mFile) + { + // It will clean pool + close(); + } + + return s; +} + +apr_status_t LLAPRFile::openMemoryMap(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, LLVolatileAPRPool* pool, S32* sizep) +{ + apr_status_t s; + S32 file_size = 0; + + //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) + { + LL_WARNS() << "Could not open file: " << filename << LL_ENDL; + mFile = NULL; + + if (sizep) + { + *sizep = 0; + } + } + else + { + 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); + } + if (sizep) *sizep = file_size; + + s = apr_mmap_create(&mMMapFile, mFile, 0, file_size, mmap_flags, apr_pool); + } + + if (!mFile || !mMMapFile) + { + // It will clean pool + close(); + } + + return s; +} + +apr_status_t LLAPRFile::openMemoryMap(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, S32 init_file_size, bool zero_out, LLVolatileAPRPool* pool, S32* sizep) +{ + apr_status_t s; + S32 file_size = 0; + + //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) + { + LL_WARNS() << "Could not open file: " << filename << LL_ENDL; + mFile = NULL; + + if (sizep) + { + *sizep = 0; + } + } + else + { + apr_off_t offset = init_file_size - 1; + if (apr_file_seek(mFile, APR_SET, &offset) == APR_SUCCESS) + { + llassert_always(offset <= 0x7fffffff); + apr_size_t one_char = 1; + apr_file_write(mFile, "\0", &one_char); + file_size = (S32)init_file_size; + offset = 0; + apr_file_seek(mFile, APR_SET, &offset); + } + if (sizep) *sizep = file_size; + + s = apr_mmap_create(&mMMapFile, mFile, 0, file_size, mmap_flags, apr_pool); + if (s != APR_SUCCESS) + { + LL_WARNS() << "Could not create Memory Map File: " << filename << LL_ENDL; + close(); + return s; + } + + // If need to zero out the file, then use memset over the memory map + if (zero_out) + { + memset(mMMapFile->mm, 0, file_size); + } + } + + if (!mFile || !mMMapFile) + { + // It will clean pool + close(); + } + + return s; +} + +apr_status_t LLAPRFile::openMemoryMap64(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, LLVolatileAPRPool* pool, S64* sizep) +{ + apr_status_t s; + S64 file_size = 0; + + //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) + { + LL_WARNS() << "Could not open file: " << filename << LL_ENDL; + mFile = NULL; + + if (sizep) + { + *sizep = 0; + } + } + else + { + apr_off_t offset = 0; + if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS) + { + llassert_always(offset <= 0x7fffffffffffffff); + file_size = offset; + offset = 0; + apr_file_seek(mFile, APR_SET, &offset); + } + if (sizep) *sizep = file_size; + + s = apr_mmap_create(&mMMapFile, mFile, 0, file_size, mmap_flags, apr_pool); + } + + if (!mFile || !mMMapFile) + { + // It will clean pool + close(); + } + + return s; +} + +apr_status_t LLAPRFile::openMemoryMap64(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, S64 init_file_size, bool zero_out, LLVolatileAPRPool* pool, S64* sizep) +{ + apr_status_t s; + S64 file_size = 0; + + //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) + { + LL_WARNS() << "Could not open file: " << filename << LL_ENDL; + mFile = NULL; + + if (sizep) + { + *sizep = 0; + } + } + else + { + apr_off_t offset = init_file_size - 1; + if (apr_file_seek(mFile, APR_SET, &offset) == APR_SUCCESS) + { + llassert_always(offset <= 0x7fffffffffffffff); + apr_size_t one_char = 1; + s = apr_file_write(mFile, "\0", &one_char); + if (s != APR_SUCCESS || one_char != 1) + { + LL_WARNS() << "Could not write to end of file: " << filename << LL_ENDL; + close(); + return s; + } + file_size = init_file_size; + offset = 0; + apr_file_seek(mFile, APR_SET, &offset); + } + if (sizep) *sizep = file_size; + + s = apr_mmap_create(&mMMapFile, mFile, 0, file_size, mmap_flags, apr_pool); + if (s != APR_SUCCESS) + { + LL_WARNS() << "Could not create Memory Map File: " << filename << LL_ENDL; + close(); + return s; + } + + // If need to zero out the file, then use memset over the memory map + if (zero_out) + { + memset(mMMapFile->mm, 0, file_size); + } + } + + if (!mFile || !mMMapFile) + { + LL_WARNS() << "Could not open file: " << filename << LL_ENDL; + // 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) { @@ -406,6 +744,41 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, boo return s; } +//use gAPRPoolp. +apr_status_t LLAPRFile::openMemoryMap(const std::string& filename, apr_int32_t flags, bool use_global_pool, apr_int32_t mmap_flags) +{ + apr_status_t s; + S64 file_size = 0; + + //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; + } + else + { + apr_off_t offset = 0; + if (apr_file_seek(mFile, APR_END, &offset) == APR_SUCCESS) + { + llassert_always(offset <= 0x7fffffffffffffff); + file_size = (S64)offset; + offset = 0; + apr_file_seek(mFile, APR_SET, &offset); + } + + s = apr_mmap_create(&mMMapFile, mFile, 0, file_size, mmap_flags, gAPRPoolp); + } + + return s; +} + // File I/O S32 LLAPRFile::read(void *buf, S32 nbytes) { @@ -429,6 +802,29 @@ S32 LLAPRFile::read(void *buf, S32 nbytes) } } +// File I/O +S64 LLAPRFile::read64(void* buf, S64 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 <= 0x7fffffffffffffff); //Use 64 bit assert instead of 32 bit + return (S64)sz; + } +} + S32 LLAPRFile::write(const void *buf, S32 nbytes) { if(!mFile) @@ -446,16 +842,109 @@ S32 LLAPRFile::write(const void *buf, S32 nbytes) } else { - llassert_always(sz <= 0x7fffffff); + llassert_always(sz <= 0x7fffffffffffffff); //Use 64 bit assert instead of 32 bit return (S32)sz; } } +S64 LLAPRFile::write64(const void* buf, S64 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 <= 0x7fffffffffffffff); + return (S64)sz; + } +} + + S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset) { return LLAPRFile::seek(mFile, where, offset) ; } +S64 LLAPRFile::seek64(apr_seek_where_t where, S64 offset) +{ + return LLAPRFile::seek64(mFile, where, offset); +} + +// Memory map offset +apr_status_t LLAPRFile::memoryMapAssign(void** addr, S32 offset) +{ + apr_status_t s = APR_SUCCESS; + // Only move the offset if the memory map is valid and was flaged to be used + if (mMMapFile) + { + s = apr_mmap_offset(addr, mMMapFile, offset); + } + else + { + LL_WARNS() << "APR File does not contain a valid Memory Map File" << LL_ENDL; + s = APR_EINVAL; + } + + return s; +} + +// Memory map offset +apr_status_t LLAPRFile::memoryMapAssign64(void** addr, S64 offset) +{ + apr_status_t s = APR_SUCCESS; + // Only move the offset if the memory map is valid and was flaged to be used + if (mMMapFile) + { + s = apr_mmap_offset(addr, mMMapFile, offset); + } + else + { + LL_WARNS() << "APR File does not contain a valid Memory Map File" << LL_ENDL; + s = APR_EINVAL; + } + + return s; +} + +// Get the file size from the file info +S64 LLAPRFile::size64() +{ + // If no file is present, then return 0 for file size + if (!mFile) return 0; + + apr_finfo_t info; + + // Get the file size information + apr_status_t s = apr_file_info_get(&info, APR_FINFO_SIZE, mFile); + + if (s == APR_SUCCESS) + { + return info.size; + } + else + { + return 0; + } + +} + +// Get the file size from the file info +S32 LLAPRFile::size() +{ + // Simply call size 64 and cast it down to 32 bit and return it + return (S32)size64(); +} + // //******************************************************************************************************************************* //static components of LLAPRFile @@ -521,11 +1010,43 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) } else { - llassert_always(apr_offset <= 0x7fffffff); + llassert_always(apr_offset <= 0x7fffffff); return (S32)apr_offset; } } +//static +S64 LLAPRFile::seek64(apr_file_t* file_handle, apr_seek_where_t where, S64 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 <= 0x7fffffffffffffff); + return (S64)apr_offset; + } +} + //static S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) { @@ -571,6 +1092,51 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb return (S32)bytes_read; } +//static +S64 LLAPRFile::readEx64(const std::string& filename, void* buf, S64 offset, S64 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::seek64(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 <= 0x7fffffffffffffff); + } + } + + //***************************************** + close(file_handle); + //***************************************** + return (S64)bytes_read; +} + //static S32 LLAPRFile::writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool) { @@ -628,6 +1194,63 @@ S32 LLAPRFile::writeEx(const std::string& filename, const void *buf, S32 offset, return (S32)bytes_written; } +//static +S64 LLAPRFile::writeEx64(const std::string& filename, const void *buf, S64 offset, S64 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::seek64(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; + if (APR_STATUS_IS_ENOSPC(s)) + { + LLApp::notifyOutOfDiskSpace(); + } + ll_apr_warn_status(s); + bytes_written = 0; + } + else + { + llassert_always(bytes_written <= 0x7fffffffffffffff); + } + } + + //***************************************** + LLAPRFile::close(file_handle); + //***************************************** + + return (S64)bytes_written; +} + //static bool LLAPRFile::remove(const std::string& filename, LLVolatileAPRPool* pool) { @@ -713,6 +1336,37 @@ S32 LLAPRFile::size(const std::string& filename, LLVolatileAPRPool* pool) } } +//static +S64 LLAPRFile::size64(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 (S64)info.size; + } + else + { + return 0; + } + } +} + //static bool LLAPRFile::makeDir(const std::string& dirname, LLVolatileAPRPool* pool) { diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 693cd7c01f..78a210f817 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -38,6 +38,7 @@ #include "apr_thread_proc.h" #include "apr_getopt.h" #include "apr_signal.h" +#include "apr_mmap.h" #include "llstring.h" @@ -123,14 +124,20 @@ class LL_COMMON_API LLVolatileAPRPool : public LLAPRPool // File IO convenience functions. // Returns NULL if the file fails to open, sets *sizep to file size if not NULL // abbreviated flags -#define LL_APR_R (APR_READ) // "r" -#define LL_APR_W (APR_CREATE|APR_TRUNCATE|APR_WRITE) // "w" -#define LL_APR_A (APR_CREATE|APR_WRITE|APR_APPEND) // "w" -#define LL_APR_RB (APR_READ|APR_BINARY) // "rb" -#define LL_APR_WB (APR_CREATE|APR_TRUNCATE|APR_WRITE|APR_BINARY) // "wb" -#define LL_APR_AB (APR_CREATE|APR_WRITE|APR_BINARY|APR_APPEND) -#define LL_APR_RPB (APR_READ|APR_WRITE|APR_BINARY) // "r+b" -#define LL_APR_WPB (APR_CREATE|APR_TRUNCATE|APR_READ|APR_WRITE|APR_BINARY) // "w+b" +// Updated to match the newer #define as the older API_ defines are deprecated. +#define LL_APR_R (APR_FOPEN_READ) // "r" +#define LL_APR_W (APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE|APR_FOPEN_WRITE) // "w" +#define LL_APR_A (APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_APPEND) // "w" +#define LL_APR_RB (APR_FOPEN_READ|APR_FOPEN_BINARY) // "rb" +#define LL_APR_WB (APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE|APR_FOPEN_WRITE|APR_FOPEN_BINARY) // "wb" +#define LL_APR_AB (APR_FOPEN_CREATE|APR_FOPEN_WRITE|APR_FOPEN_BINARY|APR_FOPEN_APPEND) +#define LL_APR_RPB (APR_FOPEN_READ|APR_FOPEN_WRITE|APR_FOPEN_BINARY) // "r+b" +#define LL_APR_WPB (APR_FOPEN_CREATE|APR_FOPEN_TRUNCATE|APR_FOPEN_READ|APR_FOPEN_WRITE|APR_FOPEN_BINARY) // "w+b" + +// Memory map read, write and read/write flags +#define LL_APR_MMAP_R (APR_MMAP_READ) // "r" +#define LL_APR_MMAP_W (APR_MMAP_WRITE) // "w" +#define LL_APR_MMAP_RW (APR_MMAP_READ|APR_MMAP_WRITE) // "rw" // //apr_file manager @@ -150,27 +157,61 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable // make this non copyable since a copy closes the file private: apr_file_t* mFile ; + apr_mmap_t* mMMapFile; LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. public: LLAPRFile() ; LLAPRFile(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL); + // Open an existing memory map file (File must be fixed size) + LLAPRFile(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, LLVolatileAPRPool* pool = NULL ); + // Opens an initialized 64 bit memory map file (File must be fixed size) + LLAPRFile(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, S64 init_file_size, bool zero_out, LLVolatileAPRPool* pool = NULL); + // Opens an initialized 32 bit memory map file (File must be fixed size) + LLAPRFile(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, S32 init_file_size, bool zero_out, LLVolatileAPRPool* pool = NULL); ~LLAPRFile() ; apr_status_t open(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL); + // Open 64 bit file + apr_status_t open64(const std::string& filename, apr_int32_t flags, LLVolatileAPRPool* pool = NULL, S64* sizep = NULL); apr_status_t open(const std::string& filename, apr_int32_t flags, bool use_global_pool); //use gAPRPoolp. + // 32 bit Memory map version of open file (File must be fixed size) + apr_status_t openMemoryMap(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL); + // 64 bit Memory map version of open file (File must be fixed size) + apr_status_t openMemoryMap64(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, LLVolatileAPRPool* pool = NULL, S64* sizep = NULL); + // 32 bit Memory map version of open file and initializes with size and can zero out (File must be fixed size) + apr_status_t openMemoryMap(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, S32 init_file_size, bool zero_out, LLVolatileAPRPool* pool = NULL, S32* sizep = NULL); + // 64 bit Memory map version of open file and initializes with size and can zero out (File must be fixed size) + apr_status_t openMemoryMap64(const std::string& filename, apr_int32_t flags, apr_int32_t mmap_flags, S64 init_file_size, bool zero_out, LLVolatileAPRPool* pool = NULL, S64* sizep = NULL); + // Memory map version of open file allowing for manual opening of the memory map file (File must be fixed size) + apr_status_t openMemoryMap(const std::string& filename, apr_int32_t flags, bool use_global_pool, apr_int32_t mmap_flags); // use gAPRPoolp. apr_status_t close() ; // Returns actual offset, -1 if seek fails S32 seek(apr_seek_where_t where, S32 offset); + // 64 bit seek (offset can be greater then 2 GB) + S64 seek64(apr_seek_where_t where, S64 offset); apr_status_t eof() { return apr_file_eof(mFile);} // Returns bytes read/written, 0 if read/write fails: S32 read(void* buf, S32 nbytes); S32 write(const void* buf, S32 nbytes); + // 64 bit read method (Number of bytes can be greater then 2 GB) + S64 read64(void* buf, S64 nbytes); + // 64 bit write method (Number of bytes can be greater then 2 GB) + S64 write64(const void* buf, S64 nbytes); apr_file_t* getFileHandle() {return mFile;} + // Assigns a variable to a memory map address (used for setting a variable pointer to the memory map (input needs to be casted) with 32 bit offset + apr_status_t memoryMapAssign(void** addr, S32 offset); + // Assigns a variable to a memory map address (used for setting a variable pointer to the memory map (input needs to be casted) with 64 bit offset + apr_status_t memoryMapAssign64(void** addr, S64 offset); + + // Helper method to get 32 bit size of file + S32 size(); + // Helper method to get 64 bit size of file + S64 size64(); // //******************************************************************************************************************************* //static components @@ -182,18 +223,25 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable static apr_file_t* open(const std::string& filename, apr_pool_t* apr_pool, apr_int32_t flags); static apr_status_t close(apr_file_t* file) ; static S32 seek(apr_file_t* file, apr_seek_where_t where, S32 offset); + // Add 64 bit seek support + static S64 seek64(apr_file_t* file, apr_seek_where_t where, S64 offset); public: // returns false if failure: 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); + // 64 bit file size support + static S64 size64(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, LLVolatileAPRPool* pool = NULL); static S32 writeEx(const std::string& filename, const void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append + // 64 bit file size support + static S64 readEx64(const std::string& filename, void *buf, S64 offset, S64 nbytes, LLVolatileAPRPool* pool = NULL); + static S64 writeEx64(const std::string& filename, const void *buf, S64 offset, S64 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append //******************************************************************************************************************************* };