This changeset hooks up many things that have been in progress and moves things about between llfilesystem and lldiskcache - there is still some bookkeeping work left but this is the first version that appears to work and actively manage the cache
parent
a0ea119623
commit
08dfc0836f
|
|
@ -25,41 +25,31 @@
|
|||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "lluuid.h"
|
||||
#include "llassettype.h"
|
||||
#include "lldir.h"
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
#include <chrono>
|
||||
|
||||
#include "lldiskcache.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <algorithm>
|
||||
|
||||
LLDiskCache::LLDiskCache(const std::string cache_dir) :
|
||||
LLDiskCache::LLDiskCache(const std::string cache_dir,
|
||||
const int max_size_bytes,
|
||||
const bool enable_cache_debug_info) :
|
||||
mCacheDir(cache_dir),
|
||||
mMaxSizeBytes(mDefaultSizeBytes)
|
||||
mMaxSizeBytes(max_size_bytes),
|
||||
mEnableCacheDebugInfo(enable_cache_debug_info)
|
||||
{
|
||||
// no access to LLControlGroup / gSavedSettings so use the system environment
|
||||
// to trigger additional debugging on top of the default "we purged the cache"
|
||||
mCacheDebugInfo = true;
|
||||
if (getenv("LL_CACHE_DEBUGGING") != nullptr)
|
||||
{
|
||||
mCacheDebugInfo = true;
|
||||
}
|
||||
// the prefix used for cache filenames to disambiguate them from other files
|
||||
mCacheFilenamePrefix = "sl_cache";
|
||||
|
||||
// create cache dir if it does not exist
|
||||
boost::filesystem::create_directory(cache_dir);
|
||||
}
|
||||
|
||||
LLDiskCache::~LLDiskCache()
|
||||
{
|
||||
}
|
||||
|
||||
void LLDiskCache::purge()
|
||||
{
|
||||
if (mCacheDebugInfo)
|
||||
if (mEnableCacheDebugInfo)
|
||||
{
|
||||
LL_INFOS() << "Total dir size before purge is " << dirFileSize(mCacheDir) << LL_ENDL;
|
||||
}
|
||||
|
|
@ -75,11 +65,14 @@ void LLDiskCache::purge()
|
|||
{
|
||||
if (boost::filesystem::is_regular_file(entry))
|
||||
{
|
||||
uintmax_t file_size = boost::filesystem::file_size(entry);
|
||||
const std::string file_path = entry.path().string();
|
||||
const std::time_t file_time = boost::filesystem::last_write_time(entry);
|
||||
if (entry.path().string().find(mCacheFilenamePrefix) != std::string::npos)
|
||||
{
|
||||
uintmax_t file_size = boost::filesystem::file_size(entry);
|
||||
const std::string file_path = entry.path().string();
|
||||
const std::time_t file_time = boost::filesystem::last_write_time(entry);
|
||||
|
||||
file_info.push_back(file_info_t(file_time, { file_size, file_path }));
|
||||
file_info.push_back(file_info_t(file_time, { file_size, file_path }));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -107,7 +100,7 @@ void LLDiskCache::purge()
|
|||
action = " KEEP:";
|
||||
}
|
||||
|
||||
if (mCacheDebugInfo)
|
||||
if (mEnableCacheDebugInfo)
|
||||
{
|
||||
// have to do this because of LL_INFO/LL_END weirdness
|
||||
std::ostringstream line;
|
||||
|
|
@ -121,7 +114,7 @@ void LLDiskCache::purge()
|
|||
}
|
||||
}
|
||||
|
||||
if (mCacheDebugInfo)
|
||||
if (mEnableCacheDebugInfo)
|
||||
{
|
||||
auto end_time = std::chrono::high_resolution_clock::now();
|
||||
auto execute_time = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time).count();
|
||||
|
|
@ -130,9 +123,78 @@ void LLDiskCache::purge()
|
|||
}
|
||||
}
|
||||
|
||||
const std::string LLDiskCache::assetTypeToString(LLAssetType::EType at)
|
||||
{
|
||||
/**
|
||||
* Make use of the C++17 (or is it 14) 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_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)
|
||||
{
|
||||
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);
|
||||
file_path << ".asset";
|
||||
|
||||
LL_INFOS() << "filepath.str() = " << file_path.str() << LL_ENDL;
|
||||
|
||||
return file_path.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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 which is used in the mechanism for purging the cache, is up to date.
|
||||
*/
|
||||
void LLDiskCache::updateFileAccessTime(const std::string file_path)
|
||||
|
|
@ -144,8 +206,8 @@ void LLDiskCache::updateFileAccessTime(const std::string file_path)
|
|||
/**
|
||||
* Clear the cache by removing all the files in the cache directory
|
||||
* individually. It's important to maintain control of which directory
|
||||
* if passed in and not let the user inadvertently (or maliciously) set
|
||||
* it to an random location like your project source or OS system directory
|
||||
* if passed in and not let the user inadvertently (or maliciously) set
|
||||
* it to an random location like your project source or OS system directory
|
||||
*/
|
||||
void LLDiskCache::clearCache(const std::string cache_dir)
|
||||
{
|
||||
|
|
@ -155,7 +217,10 @@ void LLDiskCache::clearCache(const std::string cache_dir)
|
|||
{
|
||||
if (boost::filesystem::is_regular_file(entry))
|
||||
{
|
||||
boost::filesystem::remove(entry);
|
||||
if (entry.path().string().find(mCacheFilenamePrefix) != std::string::npos)
|
||||
{
|
||||
boost::filesystem::remove(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -181,7 +246,10 @@ uintmax_t LLDiskCache::dirFileSize(const std::string dir)
|
|||
{
|
||||
if (boost::filesystem::is_regular_file(entry))
|
||||
{
|
||||
total_file_size += boost::filesystem::file_size(entry);
|
||||
if (entry.path().string().find(mCacheFilenamePrefix) != std::string::npos)
|
||||
{
|
||||
total_file_size += boost::filesystem::file_size(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,15 +27,50 @@
|
|||
#ifndef _LLDISKCACHE
|
||||
#define _LLDISKCACHE
|
||||
|
||||
class LLDiskCache
|
||||
#include "llsingleton.h"
|
||||
|
||||
class LLDiskCache :
|
||||
public LLParamSingleton<LLDiskCache>
|
||||
{
|
||||
public:
|
||||
LLDiskCache(const std::string cache_dir);
|
||||
~LLDiskCache();
|
||||
LLSINGLETON(LLDiskCache,
|
||||
const std::string cache_dir,
|
||||
const int max_size_bytes,
|
||||
const bool enable_cache_debug_info);
|
||||
virtual ~LLDiskCache() = default;
|
||||
|
||||
public:
|
||||
///**
|
||||
// * The location of the cache dir is set in llappviewer at startup via the
|
||||
// * saved settings parameters. We do not have access to those saved settings
|
||||
// * here in LLCommon so we must provide an accessor for other classes to use
|
||||
// * when they need it - e.g. LLFilesystem needs the path so it can write files
|
||||
// * to it.
|
||||
// */
|
||||
//const std::string getCacheDirName() { return mCacheDir; }
|
||||
|
||||
///**
|
||||
// * Each cache filename has a prefix inserted (see definition of the
|
||||
// * mCacheFilenamePrefix variable below for why) but the LLFileSystem
|
||||
// * component needs access to it to in order to create the file so we
|
||||
// * expose it by a getter here.
|
||||
// */
|
||||
//const std::string getCacheFilenamePrefix() { return mCacheFilenamePrefix; }
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Construct a filename and path to it based on the file meta data
|
||||
* (id, asset type, additional 'extra' info like discard level perhaps)
|
||||
* Worth pointing out that this function used to be in LLFileSystem but
|
||||
* 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 which is used in the mechanism for purging the cache, is up to date.
|
||||
*/
|
||||
void updateFileAccessTime(const std::string file_path);
|
||||
|
|
@ -51,28 +86,26 @@ class LLDiskCache
|
|||
*/
|
||||
void clearCache(const std::string cache_dir);
|
||||
|
||||
/**
|
||||
* Manage max size in bytes of cache - use a discrete setter/getter so the value can
|
||||
* be changed in the preferences and cache cleared/purged without restarting viewer
|
||||
* to instantiate this class again.
|
||||
*/
|
||||
void setMaxSizeBytes(const uintmax_t size_bytes) { mMaxSizeBytes = size_bytes; }
|
||||
uintmax_t getMaxSizeBytes() const { return mMaxSizeBytes; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* Utility function to gather the total size the files in a given
|
||||
* directory. Primarily used here to determine the directory size
|
||||
* 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);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Default of 20MB seems reasonable - it will likely be reset
|
||||
* immediately anyway using a value from the Viewer settings
|
||||
* The maximum size of the cache in bytes. After purge is called, the
|
||||
* total size of the cache files in the cache directory will be
|
||||
* less than this value
|
||||
*/
|
||||
const uintmax_t mDefaultSizeBytes = 20 * 1024 * 1024;
|
||||
uintmax_t mMaxSizeBytes;
|
||||
|
||||
/**
|
||||
|
|
@ -84,11 +117,20 @@ class LLDiskCache
|
|||
std::string mCacheDir;
|
||||
|
||||
/**
|
||||
* This is set from the CacheDebugInfo global setting and
|
||||
* when enabled, displays additional debugging information in
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* When enabled, displays additional debugging information in
|
||||
* various parts of the code
|
||||
*/
|
||||
bool mCacheDebugInfo;
|
||||
bool mEnableCacheDebugInfo;
|
||||
};
|
||||
|
||||
#endif // _LLDISKCACHE
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/**
|
||||
/**
|
||||
* @file filesystem.h
|
||||
* @brief Simulate local file system operations.
|
||||
* @Note The initial implementation does actually use standard C++
|
||||
|
|
@ -8,21 +8,21 @@
|
|||
* $LicenseInfo:firstyear=2002&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$
|
||||
*/
|
||||
|
|
@ -36,139 +36,74 @@
|
|||
|
||||
#include <fstream>
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait");
|
||||
LLDiskCache* LLFileSystem::mDiskCache = 0;
|
||||
std::string LLFileSystem::mCacheDirName = "cache";
|
||||
|
||||
LLFileSystem::LLFileSystem(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode)
|
||||
LLFileSystem::LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_type, S32 mode)
|
||||
{
|
||||
mFileType = file_type;
|
||||
mFileID = file_id;
|
||||
mPosition = 0;
|
||||
mFileType = file_type;
|
||||
mFileID = file_id;
|
||||
mPosition = 0;
|
||||
mBytesRead = 0;
|
||||
mReadComplete = FALSE;
|
||||
mMode = mode;
|
||||
mMode = mode;
|
||||
}
|
||||
|
||||
LLFileSystem::~LLFileSystem()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string assetTypeToString(LLAssetType::EType at)
|
||||
{
|
||||
/**
|
||||
* Make use of the C++17 (or is it 14) 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_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 LLFileSystem::idToFilepath(const std::string id, LLAssetType::EType at)
|
||||
{
|
||||
/**
|
||||
* For the moment this is just {UUID}_{ASSET_TYPE}.txt but of
|
||||
* course, will be greatly expanded upon
|
||||
*/
|
||||
std::ostringstream ss;
|
||||
ss << "00cache_";
|
||||
ss << id;
|
||||
ss << "_";
|
||||
ss << assetTypeToString(at);
|
||||
ss << ".txt";
|
||||
|
||||
const std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, mCacheDirName, ss.str());
|
||||
|
||||
return filepath;
|
||||
}
|
||||
|
||||
// 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 filename = idToFilepath(id_str, file_type);
|
||||
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (file.is_open())
|
||||
{
|
||||
file.seekg(0, std::ios::end);
|
||||
return file.tellg() > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLFileSystem::removeFile(const LLUUID &file_id, const LLAssetType::EType file_type)
|
||||
bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType file_type)
|
||||
{
|
||||
std::string id_str;
|
||||
file_id.toString(id_str);
|
||||
const std::string filename = idToFilepath(id_str, file_type);
|
||||
|
||||
const std::string extra_info = "";
|
||||
const std::string filename = LLDiskCache::getInstance()->metaDataToFilepath(id_str, file_type, extra_info);
|
||||
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (file.is_open())
|
||||
{
|
||||
file.seekg(0, std::ios::end);
|
||||
return file.tellg() > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLFileSystem::removeFile(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);
|
||||
|
||||
std::remove(filename.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// static
|
||||
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)
|
||||
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 old_filename = idToFilepath(old_id_str, old_file_type);
|
||||
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 = idToFilepath(new_id_str, new_file_type);
|
||||
const std::string new_filename = LLDiskCache::getInstance()->metaDataToFilepath(new_id_str, new_file_type, extra_info);
|
||||
|
||||
if (std::rename(old_filename.c_str(), new_filename.c_str()))
|
||||
{
|
||||
// We would like to return FALSE here indicating the operation
|
||||
// failed but the original code does not and doing so seems to
|
||||
// break a lot of things so we go with the flow...
|
||||
// break a lot of things so we go with the flow...
|
||||
//return FALSE;
|
||||
}
|
||||
|
||||
|
|
@ -176,11 +111,12 @@ bool LLFileSystem::renameFile(const LLUUID &old_file_id, const LLAssetType::ETyp
|
|||
}
|
||||
|
||||
// static
|
||||
S32 LLFileSystem::getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type)
|
||||
S32 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type)
|
||||
{
|
||||
std::string id_str;
|
||||
file_id.toString(id_str);
|
||||
const std::string filename = idToFilepath(id_str, file_type);
|
||||
const std::string extra_info = "";
|
||||
const std::string filename = LLDiskCache::getInstance()->metaDataToFilepath(id_str, file_type, extra_info);
|
||||
|
||||
S32 file_size = 0;
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
|
|
@ -193,15 +129,14 @@ S32 LLFileSystem::getFileSize(const LLUUID &file_id, const LLAssetType::EType fi
|
|||
return file_size;
|
||||
}
|
||||
|
||||
BOOL LLFileSystem::read(U8 *buffer, S32 bytes, BOOL async, F32 priority)
|
||||
BOOL LLFileSystem::read(U8* buffer, S32 bytes)
|
||||
{
|
||||
BOOL success = TRUE;
|
||||
|
||||
mReadComplete = FALSE;
|
||||
BOOL success = TRUE;
|
||||
|
||||
std::string id;
|
||||
mFileID.toString(id);
|
||||
const std::string filename = idToFilepath(id, mFileType);
|
||||
const std::string extra_info = "";
|
||||
const std::string filename = LLDiskCache::getInstance()->metaDataToFilepath(id, mFileType, extra_info);
|
||||
|
||||
std::ifstream file(filename, std::ios::binary);
|
||||
if (file.is_open())
|
||||
|
|
@ -226,44 +161,33 @@ BOOL LLFileSystem::read(U8 *buffer, S32 bytes, BOOL async, F32 priority)
|
|||
{
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
mReadComplete = TRUE;
|
||||
}
|
||||
|
||||
// update the last access time for the file - this is required
|
||||
// update the last access time for the file - this is required
|
||||
// even though we are reading and not writing because this is the
|
||||
// way the cache works - it relies on a valid "last accessed time" for
|
||||
// each file so it knows how to remove the oldest, unused files
|
||||
LLFileSystem::mDiskCache->updateFileAccessTime(filename);
|
||||
LLDiskCache::getInstance()->updateFileAccessTime(filename);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
BOOL LLFileSystem::isReadComplete()
|
||||
{
|
||||
if (mReadComplete)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
S32 LLFileSystem::getLastBytesRead()
|
||||
{
|
||||
return mBytesRead;
|
||||
return mBytesRead;
|
||||
}
|
||||
|
||||
BOOL LLFileSystem::eof()
|
||||
{
|
||||
return mPosition >= getSize();
|
||||
return mPosition >= getSize();
|
||||
}
|
||||
|
||||
BOOL LLFileSystem::write(const U8 *buffer, S32 bytes)
|
||||
BOOL LLFileSystem::write(const U8* buffer, S32 bytes)
|
||||
{
|
||||
std::string id_str;
|
||||
mFileID.toString(id_str);
|
||||
const std::string filename = idToFilepath(id_str, mFileType);
|
||||
const std::string extra_info = "";
|
||||
const std::string filename = LLDiskCache::getInstance()->metaDataToFilepath(id_str, mFileType, extra_info);
|
||||
|
||||
BOOL success = FALSE;
|
||||
|
||||
|
|
@ -295,37 +219,37 @@ BOOL LLFileSystem::write(const U8 *buffer, S32 bytes)
|
|||
|
||||
BOOL LLFileSystem::seek(S32 offset, S32 origin)
|
||||
{
|
||||
if (-1 == origin)
|
||||
{
|
||||
origin = mPosition;
|
||||
}
|
||||
if (-1 == origin)
|
||||
{
|
||||
origin = mPosition;
|
||||
}
|
||||
|
||||
S32 new_pos = origin + offset;
|
||||
S32 new_pos = origin + offset;
|
||||
|
||||
S32 size = getSize();
|
||||
S32 size = getSize();
|
||||
|
||||
if (new_pos > size)
|
||||
{
|
||||
LL_WARNS() << "Attempt to seek past end of file" << LL_ENDL;
|
||||
if (new_pos > size)
|
||||
{
|
||||
LL_WARNS() << "Attempt to seek past end of file" << LL_ENDL;
|
||||
|
||||
mPosition = size;
|
||||
return FALSE;
|
||||
}
|
||||
else if (new_pos < 0)
|
||||
{
|
||||
LL_WARNS() << "Attempt to seek past beginning of file" << LL_ENDL;
|
||||
mPosition = size;
|
||||
return FALSE;
|
||||
}
|
||||
else if (new_pos < 0)
|
||||
{
|
||||
LL_WARNS() << "Attempt to seek past beginning of file" << LL_ENDL;
|
||||
|
||||
mPosition = 0;
|
||||
return FALSE;
|
||||
}
|
||||
mPosition = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mPosition = new_pos;
|
||||
return TRUE;
|
||||
mPosition = new_pos;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
S32 LLFileSystem::tell() const
|
||||
{
|
||||
return mPosition;
|
||||
return mPosition;
|
||||
}
|
||||
|
||||
S32 LLFileSystem::getSize()
|
||||
|
|
@ -335,11 +259,11 @@ S32 LLFileSystem::getSize()
|
|||
|
||||
S32 LLFileSystem::getMaxSize()
|
||||
{
|
||||
// offer up a huge size since we don't care what the max is
|
||||
// offer up a huge size since we don't care what the max is
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
BOOL LLFileSystem::rename(const LLUUID &new_id, const LLAssetType::EType new_type)
|
||||
BOOL LLFileSystem::rename(const LLUUID& new_id, const LLAssetType::EType new_type)
|
||||
{
|
||||
LLFileSystem::renameFile(mFileID, mFileType, new_id, new_type);
|
||||
|
||||
|
|
@ -355,19 +279,3 @@ BOOL LLFileSystem::remove()
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFileSystem::initClass()
|
||||
{
|
||||
const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, mCacheDirName);
|
||||
|
||||
LLFileSystem::mDiskCache = new LLDiskCache(cache_dir);
|
||||
|
||||
mDiskCache->purge();
|
||||
}
|
||||
|
||||
// static
|
||||
void LLFileSystem::cleanupClass()
|
||||
{
|
||||
delete LLFileSystem::mDiskCache;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/**
|
||||
/**
|
||||
/**
|
||||
/**
|
||||
* @file filesystem.h
|
||||
* @brief Simulate local file system operations.
|
||||
* @Note The initial implementation does actually use standard C++
|
||||
|
|
@ -9,21 +9,21 @@
|
|||
* $LicenseInfo:firstyear=2002&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$
|
||||
*/
|
||||
|
|
@ -37,51 +37,43 @@
|
|||
|
||||
class LLFileSystem
|
||||
{
|
||||
public:
|
||||
LLFileSystem(const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode = LLFileSystem::READ);
|
||||
~LLFileSystem();
|
||||
public:
|
||||
LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_type, S32 mode = LLFileSystem::READ);
|
||||
~LLFileSystem();
|
||||
|
||||
BOOL read(U8 *buffer, S32 bytes, BOOL async = FALSE, F32 priority = 128.f); /* Flawfinder: ignore */
|
||||
BOOL isReadComplete();
|
||||
S32 getLastBytesRead();
|
||||
BOOL eof();
|
||||
BOOL read(U8* buffer, S32 bytes);
|
||||
S32 getLastBytesRead();
|
||||
BOOL eof();
|
||||
|
||||
BOOL write(const U8 *buffer, S32 bytes);
|
||||
BOOL seek(S32 offset, S32 origin = -1);
|
||||
S32 tell() const;
|
||||
BOOL write(const U8* buffer, S32 bytes);
|
||||
BOOL seek(S32 offset, S32 origin = -1);
|
||||
S32 tell() const;
|
||||
|
||||
S32 getSize();
|
||||
S32 getMaxSize();
|
||||
BOOL rename(const LLUUID &new_id, const LLAssetType::EType new_type);
|
||||
BOOL remove();
|
||||
S32 getSize();
|
||||
S32 getMaxSize();
|
||||
BOOL rename(const LLUUID& new_id, const LLAssetType::EType new_type);
|
||||
BOOL remove();
|
||||
|
||||
static bool getExists(const LLUUID &file_id, const LLAssetType::EType file_type);
|
||||
static bool removeFile(const LLUUID &file_id, const LLAssetType::EType file_type);
|
||||
static bool renameFile(const LLUUID &old_file_id, const LLAssetType::EType old_file_type,
|
||||
const LLUUID &new_file_id, const LLAssetType::EType new_file_type);
|
||||
static S32 getFileSize(const LLUUID &file_id, const LLAssetType::EType file_type);
|
||||
|
||||
static void initClass();
|
||||
static void cleanupClass();
|
||||
static bool getExists(const LLUUID& file_id, const LLAssetType::EType file_type);
|
||||
static bool removeFile(const LLUUID& file_id, const LLAssetType::EType file_type);
|
||||
static bool renameFile(const LLUUID& old_file_id, const LLAssetType::EType old_file_type,
|
||||
const LLUUID& new_file_id, const LLAssetType::EType new_file_type);
|
||||
static S32 getFileSize(const LLUUID& file_id, const LLAssetType::EType file_type);
|
||||
|
||||
public:
|
||||
static const S32 READ;
|
||||
static const S32 WRITE;
|
||||
static const S32 READ_WRITE;
|
||||
static const S32 APPEND;
|
||||
|
||||
protected:
|
||||
LLAssetType::EType mFileType;
|
||||
BOOL mReadComplete;
|
||||
LLUUID mFileID;
|
||||
S32 mPosition;
|
||||
S32 mMode;
|
||||
S32 mBytesRead;
|
||||
public:
|
||||
static const S32 READ;
|
||||
static const S32 WRITE;
|
||||
static const S32 READ_WRITE;
|
||||
static const S32 APPEND;
|
||||
|
||||
private:
|
||||
static const std::string idToFilepath(const std::string id, LLAssetType::EType at);
|
||||
static std::string mCacheDirName;
|
||||
static LLDiskCache* mDiskCache;
|
||||
protected:
|
||||
LLAssetType::EType mFileType;
|
||||
LLUUID mFileID;
|
||||
S32 mPosition;
|
||||
S32 mMode;
|
||||
S32 mBytesRead;
|
||||
//private:
|
||||
// static const std::string idToFilepath(const std::string id, LLAssetType::EType at);
|
||||
};
|
||||
|
||||
#endif // LL_FILESYSTEM_H
|
||||
|
|
|
|||
|
|
@ -1351,10 +1351,10 @@
|
|||
<key>Value</key>
|
||||
<integer>23</integer>
|
||||
</map>
|
||||
<key>CacheDebugInfo</key>
|
||||
<key>EnableCacheDebugInfo</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>When enabled, display additional cache debugging information</string>
|
||||
<string>When set, display additional cache debugging information</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
|
|
@ -1362,6 +1362,28 @@
|
|||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>DiskCacheMaxSizeMB</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The maximum number of MB to use for the new disk cache</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>U32</string>
|
||||
<key>Value</key>
|
||||
<integer>10</integer>
|
||||
</map>
|
||||
<key>DiskCacheDirName</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>The name of the disk cache (within the standard Viewer disk cache directory)</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>String</string>
|
||||
<key>Value</key>
|
||||
<string>dcache</string>
|
||||
</map>
|
||||
<key>CacheLocation</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@
|
|||
#include "lllogininstance.h"
|
||||
#include "llprogressview.h"
|
||||
#include "llvocache.h"
|
||||
#include "lldiskcache.h"
|
||||
#include "llvopartgroup.h"
|
||||
#include "llweb.h"
|
||||
#include "llfloatertexturefetchdebugger.h"
|
||||
|
|
@ -115,7 +116,6 @@
|
|||
#include "llprimitive.h"
|
||||
#include "llurlaction.h"
|
||||
#include "llurlentry.h"
|
||||
#include "llfilesystem.h"
|
||||
#include "llvolumemgr.h"
|
||||
#include "llxfermanager.h"
|
||||
#include "llphysicsextensions.h"
|
||||
|
|
@ -1855,9 +1855,6 @@ bool LLAppViewer::cleanup()
|
|||
SUBSYSTEM_CLEANUP(LLWorldMapView);
|
||||
SUBSYSTEM_CLEANUP(LLFolderViewItem);
|
||||
|
||||
LL_INFOS() << "Cleaning up disk cache" << LL_ENDL;
|
||||
SUBSYSTEM_CLEANUP(LLFileSystem);
|
||||
|
||||
LL_INFOS() << "Saving Data" << LL_ENDL;
|
||||
|
||||
// Store the time of our current logoff
|
||||
|
|
@ -4111,6 +4108,9 @@ bool LLAppViewer::initCache()
|
|||
{
|
||||
LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
|
||||
purgeCache();
|
||||
|
||||
// purge the new C++ file system based cache
|
||||
LLDiskCache::getInstance()->purge();
|
||||
}
|
||||
|
||||
LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache"));
|
||||
|
|
@ -4131,7 +4131,12 @@ bool LLAppViewer::initCache()
|
|||
|
||||
LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion());
|
||||
|
||||
LLFileSystem::initClass();
|
||||
// initialize the new disk cache using saved settings
|
||||
const std::string cache_dir_name = gSavedSettings.getString("DiskCacheDirName");
|
||||
const unsigned int cache_max_bytes = gSavedSettings.getU32("DiskCacheMaxSizeMB") * 1024 * 1024;
|
||||
const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo");
|
||||
const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name);
|
||||
LLDiskCache::initParamSingleton(cache_dir, cache_max_bytes, enable_cache_debug_info);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue