diff options
| author | Erik Kundiman <erik@megapahit.org> | 2024-08-31 21:25:47 +0800 | 
|---|---|---|
| committer | Erik Kundiman <erik@megapahit.org> | 2024-09-01 20:43:42 +0800 | 
| commit | 95582654e49422d51b55665c3f2821c848ad1cb8 (patch) | |
| tree | d6d03a887b8e1b6c3be1b139d63b1638c5d0fdcd /indra/llfilesystem | |
| parent | ab3f483a3e5ed213882a83b882095cfdb6a4de57 (diff) | |
| parent | b0fefd62adbf51f32434ba077e9f52d8a9241d15 (diff) | |
Merge remote-tracking branch 'secondlife/release/2024.08-DeltaFPS' into 2024.08-DeltaFPS
Diffstat (limited to 'indra/llfilesystem')
| -rw-r--r-- | indra/llfilesystem/lldir.cpp | 8 | ||||
| -rw-r--r-- | indra/llfilesystem/lldiskcache.cpp | 176 | ||||
| -rw-r--r-- | indra/llfilesystem/lldiskcache.h | 33 | ||||
| -rw-r--r-- | indra/llfilesystem/llfilesystem.cpp | 139 | ||||
| -rw-r--r-- | indra/llfilesystem/llfilesystem.h | 21 | 
5 files changed, 135 insertions, 242 deletions
| diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp index 42e91963c1..7b03143053 100644 --- a/indra/llfilesystem/lldir.cpp +++ b/indra/llfilesystem/lldir.cpp @@ -201,15 +201,15 @@ U32 LLDir::deleteDirAndContents(const std::string& dir_name)          boost::filesystem::path dir_path(dir_name);  #endif -       if (boost::filesystem::exists (dir_path)) +       if (boost::filesystem::exists(dir_path))         { -          if (!boost::filesystem::is_empty (dir_path)) +          if (!boost::filesystem::is_empty(dir_path))            {   // Directory has content -             num_deleted = boost::filesystem::remove_all (dir_path); +             num_deleted = (U32)boost::filesystem::remove_all(dir_path);            }            else            {   // Directory is empty -             boost::filesystem::remove (dir_path); +             boost::filesystem::remove(dir_path);            }         }      } diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp index da2e960ed3..49904911a9 100644 --- a/indra/llfilesystem/lldiskcache.cpp +++ b/indra/llfilesystem/lldiskcache.cpp @@ -39,15 +39,25 @@  #include "lldiskcache.h" -LLDiskCache::LLDiskCache(const std::string cache_dir, + /** +  * The prefix inserted at the start of a cache file filename to +  * help identify it as a cache file. It's probably not required +  * (just the presence in the cache folder is enough) but I am +  * paranoid about the cache folder being set to something bad +  * like the users' OS system dir by mistake or maliciously and +  * this will help to offset any damage if that happens. +  */ +static const std::string CACHE_FILENAME_PREFIX("sl_cache"); + +std::string LLDiskCache::sCacheDir; + +LLDiskCache::LLDiskCache(const std::string& cache_dir,                           const uintmax_t max_size_bytes,                           const bool enable_cache_debug_info) : -    mCacheDir(cache_dir),      mMaxSizeBytes(max_size_bytes),      mEnableCacheDebugInfo(enable_cache_debug_info)  { -    mCacheFilenamePrefix = "sl_cache"; - +    sCacheDir = cache_dir;      LLFile::mkdir(cache_dir);  } @@ -83,7 +93,7 @@ void LLDiskCache::purge()  {      if (mEnableCacheDebugInfo)      { -        LL_INFOS() << "Total dir size before purge is " << dirFileSize(mCacheDir) << LL_ENDL; +        LL_INFOS() << "Total dir size before purge is " << dirFileSize(sCacheDir) << LL_ENDL;      }      boost::system::error_code ec; @@ -93,9 +103,9 @@ void LLDiskCache::purge()      std::vector<file_info_t> file_info;  #if LL_WINDOWS -    std::wstring cache_path(utf8str_to_utf16str(mCacheDir)); +    std::wstring cache_path(utf8str_to_utf16str(sCacheDir));  #else -    std::string cache_path(mCacheDir); +    std::string cache_path(sCacheDir);  #endif      if (boost::filesystem::is_directory(cache_path, ec) && !ec.failed())      { @@ -104,7 +114,7 @@ void LLDiskCache::purge()          {              if (boost::filesystem::is_regular_file(*iter, ec) && !ec.failed())              { -                if ((*iter).path().string().find(mCacheFilenamePrefix) != std::string::npos) +                if ((*iter).path().string().find(CACHE_FILENAME_PREFIX) != std::string::npos)                  {                      uintmax_t file_size = boost::filesystem::file_size(*iter, ec);                      if (ec.failed()) @@ -181,152 +191,22 @@ void LLDiskCache::purge()              LL_INFOS() << line.str() << LL_ENDL;          } -        LL_INFOS() << "Total dir size after purge is " << dirFileSize(mCacheDir) << LL_ENDL; +        LL_INFOS() << "Total dir size after purge is " << dirFileSize(sCacheDir) << LL_ENDL;          LL_INFOS() << "Cache purge took " << execute_time << " ms to execute for " << file_info.size() << " files" << LL_ENDL;      }  } -const std::string LLDiskCache::assetTypeToString(LLAssetType::EType at) -{ -    /** -     * Make use of the handy C++17  feature that allows -     * for inline initialization of an std::map<> -     */ -    typedef std::map<LLAssetType::EType, std::string> asset_type_to_name_t; -    asset_type_to_name_t asset_type_to_name = -    { -        { LLAssetType::AT_TEXTURE, "TEXTURE" }, -        { LLAssetType::AT_SOUND, "SOUND" }, -        { LLAssetType::AT_CALLINGCARD, "CALLINGCARD" }, -        { LLAssetType::AT_LANDMARK, "LANDMARK" }, -        { LLAssetType::AT_SCRIPT, "SCRIPT" }, -        { LLAssetType::AT_CLOTHING, "CLOTHING" }, -        { LLAssetType::AT_OBJECT, "OBJECT" }, -        { LLAssetType::AT_NOTECARD, "NOTECARD" }, -        { LLAssetType::AT_CATEGORY, "CATEGORY" }, -        { LLAssetType::AT_LSL_TEXT, "LSL_TEXT" }, -        { LLAssetType::AT_LSL_BYTECODE, "LSL_BYTECODE" }, -        { LLAssetType::AT_TEXTURE_TGA, "TEXTURE_TGA" }, -        { LLAssetType::AT_BODYPART, "BODYPART" }, -        { LLAssetType::AT_SOUND_WAV, "SOUND_WAV" }, -        { LLAssetType::AT_IMAGE_TGA, "IMAGE_TGA" }, -        { LLAssetType::AT_IMAGE_JPEG, "IMAGE_JPEG" }, -        { LLAssetType::AT_ANIMATION, "ANIMATION" }, -        { LLAssetType::AT_GESTURE, "GESTURE" }, -        { LLAssetType::AT_SIMSTATE, "SIMSTATE" }, -        { LLAssetType::AT_LINK, "LINK" }, -        { LLAssetType::AT_LINK_FOLDER, "LINK_FOLDER" }, -        { LLAssetType::AT_MARKETPLACE_FOLDER, "MARKETPLACE_FOLDER" }, -        { LLAssetType::AT_WIDGET, "WIDGET" }, -        { LLAssetType::AT_PERSON, "PERSON" }, -        { LLAssetType::AT_MESH, "MESH" }, -        { LLAssetType::AT_SETTINGS, "SETTINGS" }, -        { LLAssetType::AT_MATERIAL, "MATERIAL" }, -        { LLAssetType::AT_GLTF, "GLTF" }, -        { LLAssetType::AT_GLTF_BIN, "GLTF_BIN" }, -        { LLAssetType::AT_UNKNOWN, "UNKNOWN" } -    }; - -    asset_type_to_name_t::iterator iter = asset_type_to_name.find(at); -    if (iter != asset_type_to_name.end()) -    { -        return iter->second; -    } - -    return std::string("UNKNOWN"); -} - -const std::string LLDiskCache::metaDataToFilepath(const std::string id, -        LLAssetType::EType at, -        const std::string extra_info) +const std::string LLDiskCache::metaDataToFilepath(const LLUUID& id, LLAssetType::EType at)  { -    std::ostringstream file_path; - -    file_path << mCacheDir; -    file_path << gDirUtilp->getDirDelimiter(); -    file_path << mCacheFilenamePrefix; -    file_path << "_"; -    file_path << id; -    file_path << "_"; -    file_path << (extra_info.empty() ? "0" : extra_info); -    //file_path << "_"; -    //file_path << assetTypeToString(at); // see  SL-14210 Prune descriptive tag from new cache filenames -                                          // for details of why it was removed. Note that if you put it -                                          // back or change the format of the filename, the cache files -                                          // files will be invalidated (and perhaps, more importantly, -                                          // never deleted unless you delete them manually). -    file_path << ".asset"; - -    return file_path.str(); -} - -void LLDiskCache::updateFileAccessTime(const std::string file_path) -{ -    /** -     * Threshold in time_t units that is used to decide if the last access time -     * time of the file is updated or not. Added as a precaution for the concern -     * outlined in SL-14582  about frequent writes on older SSDs reducing their -     * lifespan. I think this is the right place for the threshold value - rather -     * than it being a pref - do comment on that Jira if you disagree... -     * -     * Let's start with 1 hour in time_t units and see how that unfolds -     */ -    const std::time_t time_threshold = 1 * 60 * 60; - -    // current time -    const std::time_t cur_time = std::time(nullptr); - -    boost::system::error_code ec; -#if LL_WINDOWS -    // file last write time -    const std::time_t last_write_time = boost::filesystem::last_write_time(utf8str_to_utf16str(file_path), ec); -    if (ec.failed()) -    { -        LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; -        return; -    } - -    // delta between cur time and last time the file was written -    const std::time_t delta_time = cur_time - last_write_time; - -    // we only write the new value if the time in time_threshold has elapsed -    // before the last one -    if (delta_time > time_threshold) -    { -        boost::filesystem::last_write_time(utf8str_to_utf16str(file_path), cur_time, ec); -    } -#else -    // file last write time -    const std::time_t last_write_time = boost::filesystem::last_write_time(file_path, ec); -    if (ec.failed()) -    { -        LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; -        return; -    } - -    // delta between cur time and last time the file was written -    const std::time_t delta_time = cur_time - last_write_time; - -    // we only write the new value if the time in time_threshold has elapsed -    // before the last one -    if (delta_time > time_threshold) -    { -        boost::filesystem::last_write_time(file_path, cur_time, ec); -    } -#endif - -    if (ec.failed()) -    { -        LL_WARNS() << "Failed to update last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; -    } +    return llformat("%s%s%s_%s_0.asset", sCacheDir.c_str(), gDirUtilp->getDirDelimiter().c_str(), CACHE_FILENAME_PREFIX.c_str(), id.asString().c_str());  }  const std::string LLDiskCache::getCacheInfo()  {      std::ostringstream cache_info; -    F32 max_in_mb = (F32)mMaxSizeBytes / (1024.0 * 1024.0); -    F32 percent_used = ((F32)dirFileSize(mCacheDir) / (F32)mMaxSizeBytes) * 100.0; +    F32 max_in_mb = (F32)mMaxSizeBytes / (1024.0f * 1024.0f); +    F32 percent_used = ((F32)dirFileSize(sCacheDir) / (F32)mMaxSizeBytes) * 100.0f;      cache_info << std::fixed;      cache_info << std::setprecision(1); @@ -346,9 +226,9 @@ void LLDiskCache::clearCache()       */      boost::system::error_code ec;  #if LL_WINDOWS -    std::wstring cache_path(utf8str_to_utf16str(mCacheDir)); +    std::wstring cache_path(utf8str_to_utf16str(sCacheDir));  #else -    std::string cache_path(mCacheDir); +    std::string cache_path(sCacheDir);  #endif      if (boost::filesystem::is_directory(cache_path, ec) && !ec.failed())      { @@ -357,7 +237,7 @@ void LLDiskCache::clearCache()          {              if (boost::filesystem::is_regular_file(*iter, ec) && !ec.failed())              { -                if ((*iter).path().string().find(mCacheFilenamePrefix) != std::string::npos) +                if ((*iter).path().string().find(CACHE_FILENAME_PREFIX) != std::string::npos)                  {                      boost::filesystem::remove(*iter, ec);                      if (ec.failed()) @@ -405,7 +285,7 @@ void LLDiskCache::removeOldVFSFiles()      }  } -uintmax_t LLDiskCache::dirFileSize(const std::string dir) +uintmax_t LLDiskCache::dirFileSize(const std::string& dir)  {      uintmax_t total_file_size = 0; @@ -431,7 +311,7 @@ uintmax_t LLDiskCache::dirFileSize(const std::string dir)          {              if (boost::filesystem::is_regular_file(*iter, ec) && !ec.failed())              { -                if ((*iter).path().string().find(mCacheFilenamePrefix) != std::string::npos) +                if ((*iter).path().string().find(CACHE_FILENAME_PREFIX) != std::string::npos)                  {                      uintmax_t file_size = boost::filesystem::file_size(*iter, ec);                      if (!ec.failed()) diff --git a/indra/llfilesystem/lldiskcache.h b/indra/llfilesystem/lldiskcache.h index b60e74f8c9..f07b26c2d7 100644 --- a/indra/llfilesystem/lldiskcache.h +++ b/indra/llfilesystem/lldiskcache.h @@ -81,7 +81,7 @@ class LLDiskCache :                       * a child of the main Viewer cache directory. Defined                       * by the setting at 'DiskCacheDirName'                       */ -                    const std::string cache_dir, +                    const std::string& cache_dir,                      /**                       * The maximum size of the cache in bytes - Based on the                       * setting at 'CacheSize' and 'DiskCachePercentOfTotal' @@ -104,16 +104,7 @@ class LLDiskCache :           * so many things had to be pushed back there to accomodate it, that I           * decided to move it here.  Still not sure that's completely right.           */ -        const std::string metaDataToFilepath(const std::string id, -                                             LLAssetType::EType at, -                                             const std::string extra_info); - -        /** -         * Update the "last write time" of a file to "now". This must be called whenever a -         * file in the cache is read (not written) so that the last time the file was -         * accessed is up to date (This is used in the mechanism for purging the cache) -         */ -        void updateFileAccessTime(const std::string file_path); +        static const std::string metaDataToFilepath(const LLUUID& id, LLAssetType::EType at);          /**           * Purge the oldest items in the cache so that the combined size of all files @@ -148,13 +139,7 @@ class LLDiskCache :           * directory. Primarily used here to determine the directory size           * before and after the cache purge           */ -        uintmax_t dirFileSize(const std::string dir); - -        /** -         * Utility function to convert an LLAssetType enum into a -         * string that we use as part of the cache file filename -         */ -        const std::string assetTypeToString(LLAssetType::EType at); +        uintmax_t dirFileSize(const std::string& dir);      private:          /** @@ -170,17 +155,7 @@ class LLDiskCache :           * setting could potentially point it at a non-cache directory (for example,           * the Windows System dir) with disastrous results.           */ -        std::string mCacheDir; - -        /** -         * The prefix inserted at the start of a cache file filename to -         * help identify it as a cache file. It's probably not required -         * (just the presence in the cache folder is enough) but I am -         * paranoid about the cache folder being set to something bad -         * like the users' OS system dir by mistake or maliciously and -         * this will help to offset any damage if that happens. -         */ -        std::string mCacheFilenamePrefix; +        static std::string sCacheDir;          /**           * When enabled, displays additional debugging information in diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp index 235aae0be3..c8ce9531c2 100644 --- a/indra/llfilesystem/llfilesystem.cpp +++ b/indra/llfilesystem/llfilesystem.cpp @@ -34,10 +34,12 @@  #include "llfasttimer.h"  #include "lldiskcache.h" -const S32 LLFileSystem::READ        = 0x00000001; -const S32 LLFileSystem::WRITE       = 0x00000002; -const S32 LLFileSystem::READ_WRITE  = 0x00000003;  // LLFileSystem::READ & LLFileSystem::WRITE -const S32 LLFileSystem::APPEND      = 0x00000006;  // 0x00000004 & LLFileSystem::WRITE +#include "boost/filesystem.hpp" + +constexpr S32 LLFileSystem::READ        = 0x00000001; +constexpr S32 LLFileSystem::WRITE       = 0x00000002; +constexpr S32 LLFileSystem::READ_WRITE  = 0x00000003;  // LLFileSystem::READ & LLFileSystem::WRITE +constexpr S32 LLFileSystem::APPEND      = 0x00000006;  // 0x00000004 & LLFileSystem::WRITE  static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait"); @@ -55,10 +57,7 @@ LLFileSystem::LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_      if (mode == LLFileSystem::READ)      {          // build the filename (TODO: we do this in a few places - perhaps we should factor into a single function) -        std::string id; -        mFileID.toString(id); -        const std::string extra_info = ""; -        const std::string filename = LLDiskCache::getInstance()->metaDataToFilepath(id, mFileType, extra_info); +        const std::string filename = LLDiskCache::metaDataToFilepath(mFileID, mFileType);          // update the last access time for the file if it exists - this is required          // even though we are reading and not writing because this is the @@ -67,22 +66,16 @@ LLFileSystem::LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_          bool exists = gDirUtilp->fileExists(filename);          if (exists)          { -            LLDiskCache::getInstance()->updateFileAccessTime(filename); +            updateFileAccessTime(filename);          }      }  } -LLFileSystem::~LLFileSystem() -{ -} -  // static  bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType file_type)  { -    std::string id_str; -    file_id.toString(id_str); -    const std::string extra_info = ""; -    const std::string filename = LLDiskCache::getInstance()->metaDataToFilepath(id_str, file_type, extra_info); +    LL_PROFILE_ZONE_SCOPED; +    const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type);      llifstream file(filename, std::ios::binary);      if (file.is_open()) @@ -96,10 +89,7 @@ bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType fil  // static  bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_error /*= 0*/)  { -    std::string id_str; -    file_id.toString(id_str); -    const std::string extra_info = ""; -    const std::string filename =  LLDiskCache::getInstance()->metaDataToFilepath(id_str, file_type, extra_info); +    const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type);      LLFile::remove(filename.c_str(), suppress_error); @@ -110,14 +100,8 @@ bool LLFileSystem::removeFile(const LLUUID& file_id, const LLAssetType::EType fi  bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::EType old_file_type,                                const LLUUID& new_file_id, const LLAssetType::EType new_file_type)  { -    std::string old_id_str; -    old_file_id.toString(old_id_str); -    const std::string extra_info = ""; -    const std::string old_filename =  LLDiskCache::getInstance()->metaDataToFilepath(old_id_str, old_file_type, extra_info); - -    std::string new_id_str; -    new_file_id.toString(new_id_str); -    const std::string new_filename =  LLDiskCache::getInstance()->metaDataToFilepath(new_id_str, new_file_type, extra_info); +    const std::string old_filename = LLDiskCache::metaDataToFilepath(old_file_id, old_file_type); +    const std::string new_filename = LLDiskCache::metaDataToFilepath(new_file_id, new_file_type);      // Rename needs the new file to not exist.      LLFileSystem::removeFile(new_file_id, new_file_type, ENOENT); @@ -128,7 +112,7 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp          // failed but the original code does not and doing so seems to          // break a lot of things so we go with the flow...          //return false; -        LL_WARNS() << "Failed to rename " << old_file_id << " to " << new_id_str << " reason: "  << strerror(errno) << LL_ENDL; +        LL_WARNS() << "Failed to rename " << old_file_id << " to " << new_file_id << " reason: " << strerror(errno) << LL_ENDL;      }      return true; @@ -137,17 +121,14 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp  // static  S32 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type)  { -    std::string id_str; -    file_id.toString(id_str); -    const std::string extra_info = ""; -    const std::string filename =  LLDiskCache::getInstance()->metaDataToFilepath(id_str, file_type, extra_info); +    const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type);      S32 file_size = 0;      llifstream file(filename, std::ios::binary);      if (file.is_open())      {          file.seekg(0, std::ios::end); -        file_size = file.tellg(); +        file_size = (S32)file.tellg();      }      return file_size; @@ -157,10 +138,7 @@ bool LLFileSystem::read(U8* buffer, S32 bytes)  {      bool success = false; -    std::string id; -    mFileID.toString(id); -    const std::string extra_info = ""; -    const std::string filename =  LLDiskCache::getInstance()->metaDataToFilepath(id, mFileType, extra_info); +    const std::string filename = LLDiskCache::metaDataToFilepath(mFileID, mFileType);      llifstream file(filename, std::ios::binary);      if (file.is_open()) @@ -175,7 +153,7 @@ bool LLFileSystem::read(U8* buffer, S32 bytes)          }          else          { -            mBytesRead = file.gcount(); +            mBytesRead = (S32)file.gcount();          }          file.close(); @@ -190,22 +168,19 @@ bool LLFileSystem::read(U8* buffer, S32 bytes)      return success;  } -S32 LLFileSystem::getLastBytesRead() +S32 LLFileSystem::getLastBytesRead() const  {      return mBytesRead;  } -bool LLFileSystem::eof() +bool LLFileSystem::eof() const  {      return mPosition >= getSize();  }  bool LLFileSystem::write(const U8* buffer, S32 bytes)  { -    std::string id_str; -    mFileID.toString(id_str); -    const std::string extra_info = ""; -    const std::string filename =  LLDiskCache::getInstance()->metaDataToFilepath(id_str, mFileType, extra_info); +    const std::string filename = LLDiskCache::metaDataToFilepath(mFileID, mFileType);      bool success = false; @@ -216,12 +191,11 @@ bool LLFileSystem::write(const U8* buffer, S32 bytes)          {              ofs.write((const char*)buffer, bytes); -            mPosition = ofs.tellp(); // <FS:Ansariel> Fix asset caching +            mPosition = (S32)ofs.tellp();              success = true;          }      } -    // <FS:Ansariel> Fix asset caching      else if (mMode == READ_WRITE)      {          // Don't truncate if file already exists @@ -245,7 +219,6 @@ bool LLFileSystem::write(const U8* buffer, S32 bytes)              }          }      } -    // </FS:Ansariel>      else      {          llofstream ofs(filename, std::ios::binary); @@ -297,12 +270,12 @@ S32 LLFileSystem::tell() const      return mPosition;  } -S32 LLFileSystem::getSize() +S32 LLFileSystem::getSize() const  {      return LLFileSystem::getFileSize(mFileID, mFileType);  } -S32 LLFileSystem::getMaxSize() +S32 LLFileSystem::getMaxSize() const  {      // offer up a huge size since we don't care what the max is      return INT_MAX; @@ -318,9 +291,69 @@ bool LLFileSystem::rename(const LLUUID& new_id, const LLAssetType::EType new_typ      return true;  } -bool LLFileSystem::remove() +bool LLFileSystem::remove() const  {      LLFileSystem::removeFile(mFileID, mFileType); -      return true;  } + +void LLFileSystem::updateFileAccessTime(const std::string& file_path) +{ +    /** +     * Threshold in time_t units that is used to decide if the last access time +     * time of the file is updated or not. Added as a precaution for the concern +     * outlined in SL-14582  about frequent writes on older SSDs reducing their +     * lifespan. I think this is the right place for the threshold value - rather +     * than it being a pref - do comment on that Jira if you disagree... +     * +     * Let's start with 1 hour in time_t units and see how that unfolds +     */ +    constexpr std::time_t time_threshold = 1 * 60 * 60; + +    // current time +    const std::time_t cur_time = std::time(nullptr); + +    boost::system::error_code ec; +#if LL_WINDOWS +    // file last write time +    const std::time_t last_write_time = boost::filesystem::last_write_time(utf8str_to_utf16str(file_path), ec); +    if (ec.failed()) +    { +        LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; +        return; +    } + +    // delta between cur time and last time the file was written +    const std::time_t delta_time = cur_time - last_write_time; + +    // we only write the new value if the time in time_threshold has elapsed +    // before the last one +    if (delta_time > time_threshold) +    { +        boost::filesystem::last_write_time(utf8str_to_utf16str(file_path), cur_time, ec); +    } +#else +    // file last write time +    const std::time_t last_write_time = boost::filesystem::last_write_time(file_path, ec); +    if (ec.failed()) +    { +        LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; +        return; +    } + +    // delta between cur time and last time the file was written +    const std::time_t delta_time = cur_time - last_write_time; + +    // we only write the new value if the time in time_threshold has elapsed +    // before the last one +    if (delta_time > time_threshold) +    { +        boost::filesystem::last_write_time(file_path, cur_time, ec); +    } +#endif + +    if (ec.failed()) +    { +        LL_WARNS() << "Failed to update last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL; +    } +} diff --git a/indra/llfilesystem/llfilesystem.h b/indra/llfilesystem/llfilesystem.h index ea1b9cf3a1..10649b6920 100644 --- a/indra/llfilesystem/llfilesystem.h +++ b/indra/llfilesystem/llfilesystem.h @@ -38,20 +38,27 @@ class LLFileSystem  {      public:          LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_type, S32 mode = LLFileSystem::READ); -        ~LLFileSystem(); +        ~LLFileSystem() = default;          bool read(U8* buffer, S32 bytes); -        S32  getLastBytesRead(); -        bool eof(); +        S32  getLastBytesRead() const; +        bool eof() const;          bool write(const U8* buffer, S32 bytes);          bool seek(S32 offset, S32 origin = -1);          S32  tell() const; -        S32 getSize(); -        S32 getMaxSize(); +        S32 getSize() const; +        S32 getMaxSize() const;          bool rename(const LLUUID& new_id, const LLAssetType::EType new_type); -        bool remove(); +        bool remove() const; + +        /** +         * Update the "last write time" of a file to "now". This must be called whenever a +         * file in the cache is read (not written) so that the last time the file was +         * accessed is up to date (This is used in the mechanism for purging the cache) +         */ +        void updateFileAccessTime(const std::string& file_path);          static bool getExists(const LLUUID& file_id, const LLAssetType::EType file_type);          static bool removeFile(const LLUUID& file_id, const LLAssetType::EType file_type, int suppress_error = 0); @@ -71,8 +78,6 @@ class LLFileSystem          S32     mPosition;          S32     mMode;          S32     mBytesRead; -//private: -//    static const std::string idToFilepath(const std::string id, LLAssetType::EType at);  };  #endif  // LL_FILESYSTEM_H | 
