summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llappviewer.cpp')
-rw-r--r--indra/newview/llappviewer.cpp293
1 files changed, 253 insertions, 40 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 67bb9db23a..2040151008 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -98,7 +98,6 @@
#include "lllogininstance.h"
#include "llprogressview.h"
#include "llvocache.h"
-#include "lldiskcache.h"
#include "llvopartgroup.h"
#include "llweb.h"
#include "llfloatertexturefetchdebugger.h"
@@ -116,6 +115,8 @@
#include "llprimitive.h"
#include "llurlaction.h"
#include "llurlentry.h"
+#include "llvfile.h"
+#include "llvfsthread.h"
#include "llvolumemgr.h"
#include "llxfermanager.h"
#include "llphysicsextensions.h"
@@ -339,6 +340,9 @@ bool gUseWireframe = FALSE;
//use for remember deferred mode in wireframe switch
bool gInitialDeferredModeForWireframe = FALSE;
+// VFS globals - see llappviewer.h
+LLVFS* gStaticVFS = NULL;
+
LLMemoryInfo gSysMemory;
U64Bytes gMemoryAllocated(0); // updated in display_stats() in llviewerdisplay.cpp
@@ -427,6 +431,12 @@ void init_default_trans_args()
default_trans_args.insert("create_account_url");
}
+//----------------------------------------------------------------------------
+// File scope definitons
+const char *VFS_DATA_FILE_BASE = "data.db2.x.";
+const char *VFS_INDEX_FILE_BASE = "index.db2.x.";
+
+
struct SettingsFile : public LLInitParam::Block<SettingsFile>
{
Mandatory<std::string> name;
@@ -962,6 +972,10 @@ bool LLAppViewer::init()
// *Note: this is where gViewerStats used to be created.
+ //
+ // Initialize the VFS, and gracefully handle initialization errors
+ //
+
if (!initCache())
{
LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL;
@@ -1356,6 +1370,7 @@ static LLTrace::BlockTimerStatHandle FTM_TEXTURE_CACHE("Texture Cache");
static LLTrace::BlockTimerStatHandle FTM_DECODE("Image Decode");
static LLTrace::BlockTimerStatHandle FTM_FETCH("Image Fetch");
+static LLTrace::BlockTimerStatHandle FTM_VFS("VFS Thread");
static LLTrace::BlockTimerStatHandle FTM_LFS("LFS Thread");
static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads");
static LLTrace::BlockTimerStatHandle FTM_IDLE("Idle");
@@ -1590,13 +1605,17 @@ bool LLAppViewer::doFrame()
work_pending += updateTextureThreads(max_time);
{
+ LL_RECORD_BLOCK_TIME(FTM_VFS);
+ io_pending += LLVFSThread::updateClass(1);
+ }
+ {
LL_RECORD_BLOCK_TIME(FTM_LFS);
io_pending += LLLFSThread::updateClass(1);
}
if (io_pending > 1000)
{
- ms_sleep(llmin(io_pending/100,100)); // give the lfs some time to catch up
+ ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up
}
total_work_pending += work_pending ;
@@ -1613,6 +1632,7 @@ bool LLAppViewer::doFrame()
}
if(!total_io_pending) //pause file threads if nothing to process.
{
+ LLVFSThread::sLocal->pause();
LLLFSThread::sLocal->pause();
}
@@ -1674,11 +1694,12 @@ S32 LLAppViewer::updateTextureThreads(F32 max_time)
return work_pending;
}
-void LLAppViewer::flushLFSIO()
+void LLAppViewer::flushVFSIO()
{
while (1)
{
- S32 pending = LLLFSThread::updateClass(0);
+ S32 pending = LLVFSThread::updateClass(0);
+ pending += LLLFSThread::updateClass(0);
if (!pending)
{
break;
@@ -1766,7 +1787,7 @@ bool LLAppViewer::cleanup()
LLKeyframeDataCache::clear();
- // End TransferManager before deleting systems it depends on (Audio, AssetStorage)
+ // End TransferManager before deleting systems it depends on (Audio, VFS, AssetStorage)
#if 0 // this seems to get us stuck in an infinite loop...
gTransferManager.cleanup();
#endif
@@ -1833,8 +1854,8 @@ bool LLAppViewer::cleanup()
LL_INFOS() << "Cache files removed" << LL_ENDL;
- // Wait for any pending LFS IO
- flushLFSIO();
+ // Wait for any pending VFS IO
+ flushVFSIO();
LL_INFOS() << "Shutting down Views" << LL_ENDL;
// Destroy the UI
@@ -1918,6 +1939,15 @@ bool LLAppViewer::cleanup()
SUBSYSTEM_CLEANUP(LLWorldMapView);
SUBSYSTEM_CLEANUP(LLFolderViewItem);
+ //
+ // Shut down the VFS's AFTER the decode manager cleans up (since it cleans up vfiles).
+ // Also after viewerwindow is deleted, since it may have image pointers (which have vfiles)
+ // Also after shutting down the messaging system since it has VFS dependencies
+
+ //
+ LL_INFOS() << "Cleaning up VFS" << LL_ENDL;
+ SUBSYSTEM_CLEANUP(LLVFile);
+
LL_INFOS() << "Saving Data" << LL_ENDL;
// Store the time of our current logoff
@@ -2004,6 +2034,7 @@ bool LLAppViewer::cleanup()
pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread
pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
+ pending += LLVFSThread::updateClass(0);
pending += LLLFSThread::updateClass(0);
F64 idle_time = idleTimer.getElapsedTimeF64();
if(!pending)
@@ -2078,11 +2109,28 @@ bool LLAppViewer::cleanup()
gTextureList.shutdown(); // shutdown again in case a callback added something
LLUIImageList::getInstance()->cleanUp();
+ // This should eventually be done in LLAppViewer
SUBSYSTEM_CLEANUP(LLImage);
+ SUBSYSTEM_CLEANUP(LLVFSThread);
SUBSYSTEM_CLEANUP(LLLFSThread);
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ LL_INFOS() << "Auditing VFS" << LL_ENDL;
+ if(gVFS)
+ {
+ gVFS->audit();
+ }
+#endif
+
LL_INFOS() << "Misc Cleanup" << LL_ENDL;
+ // For safety, the LLVFS has to be deleted *after* LLVFSThread. This should be cleaned up.
+ // (LLVFS doesn't know about LLVFSThread so can't kill pending requests) -Steve
+ delete gStaticVFS;
+ gStaticVFS = NULL;
+ delete gVFS;
+ gVFS = NULL;
+
gSavedSettings.cleanup();
LLUIColorTable::instance().clear();
@@ -2164,6 +2212,7 @@ bool LLAppViewer::initThreads()
LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange"));
+ LLVFSThread::initClass(enable_threads && false);
LLLFSThread::initClass(enable_threads && false);
// Image decoding
@@ -3165,6 +3214,10 @@ LLSD LLAppViewer::getViewerInfo() const
info["GPU_SHADERS"] = gSavedSettings.getBOOL("RenderDeferred") ? "Enabled" : "Disabled";
info["TEXTURE_MEMORY"] = gSavedSettings.getS32("TextureMemory");
+ LLSD substitution;
+ substitution["datetime"] = (S32)(gVFS ? gVFS->creationTime() : 0);
+ info["VFS_TIME"] = LLTrans::getString("AboutTime", substitution);
+
#if LL_DARWIN
info["HIDPI"] = gHiDPISupport;
#endif
@@ -3256,9 +3309,6 @@ LLSD LLAppViewer::getViewerInfo() const
info["SERVER_RELEASE_NOTES_URL"] = mServerReleaseNotesURL;
}
- // populate field for new local disk cache with some details
- info["DISK_CACHE_INFO"] = LLDiskCache::getInstance()->getCacheInfo();
-
return info;
}
@@ -3908,7 +3958,7 @@ void LLAppViewer::forceQuit()
void LLAppViewer::fastQuit(S32 error_code)
{
// finish pending transfers
- flushLFSIO();
+ flushVFSIO();
// let sim know we're logging out
sendLogoutRequest();
// flush network buffers by shutting down messaging system
@@ -4097,6 +4147,39 @@ void LLAppViewer::migrateCacheDirectory()
#endif // LL_WINDOWS || LL_DARWIN
}
+void dumpVFSCaches()
+{
+ LL_INFOS() << "======= Static VFS ========" << LL_ENDL;
+ gStaticVFS->listFiles();
+#if LL_WINDOWS
+ LL_INFOS() << "======= Dumping static VFS to StaticVFSDump ========" << LL_ENDL;
+ WCHAR w_str[MAX_PATH];
+ GetCurrentDirectory(MAX_PATH, w_str);
+ S32 res = LLFile::mkdir("StaticVFSDump");
+ if (res == -1)
+ {
+ LL_WARNS() << "Couldn't create dir StaticVFSDump" << LL_ENDL;
+ }
+ SetCurrentDirectory(utf8str_to_utf16str("StaticVFSDump").c_str());
+ gStaticVFS->dumpFiles();
+ SetCurrentDirectory(w_str);
+#endif
+
+ LL_INFOS() << "========= Dynamic VFS ====" << LL_ENDL;
+ gVFS->listFiles();
+#if LL_WINDOWS
+ LL_INFOS() << "========= Dumping dynamic VFS to VFSDump ====" << LL_ENDL;
+ res = LLFile::mkdir("VFSDump");
+ if (res == -1)
+ {
+ LL_WARNS() << "Couldn't create dir VFSDump" << LL_ENDL;
+ }
+ SetCurrentDirectory(utf8str_to_utf16str("VFSDump").c_str());
+ gVFS->dumpFiles();
+ SetCurrentDirectory(w_str);
+#endif
+}
+
//static
U32 LLAppViewer::getTextureCacheVersion()
{
@@ -4123,19 +4206,6 @@ bool LLAppViewer::initCache()
LLAppViewer::getTextureCache()->setReadOnly(read_only) ;
LLVOCache::initParamSingleton(read_only);
- // initialize the new disk cache using saved settings
- const std::string cache_dir_name = gSavedSettings.getString("DiskCacheDirName");
-
- // note that the maximum size of this cache is defined as a percentage of the
- // total cache size - the 'CacheSize' pref - for all caches.
- const unsigned int cache_total_size_mb = gSavedSettings.getU32("CacheSize");
- const double disk_cache_percent = gSavedSettings.getF32("DiskCachePercentOfTotal");
- const unsigned int disk_cache_mb = cache_total_size_mb * disk_cache_percent / 100;
- const unsigned int disk_cache_bytes = disk_cache_mb * 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, disk_cache_bytes, enable_cache_debug_info);
-
bool texture_cache_mismatch = false;
if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion())
{
@@ -4182,21 +4252,10 @@ bool LLAppViewer::initCache()
gSavedSettings.setString("CacheLocationTopFolder", "");
}
- if (!read_only)
+ if (mPurgeCache && !read_only)
{
- if (mPurgeCache)
- {
- LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
- purgeCache();
-
- // clear the new C++ file system based cache
- LLDiskCache::getInstance()->clearCache();
- }
- else
- {
- // purge excessive files from the new file system based cache
- LLDiskCache::getInstance()->purge();
- }
+ LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
+ purgeCache();
}
LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache"));
@@ -4206,18 +4265,172 @@ bool LLAppViewer::initCache()
const S32 MB = 1024 * 1024;
const S64 MIN_CACHE_SIZE = 256 * MB;
const S64 MAX_CACHE_SIZE = 9984ll * MB;
+ const S64 MAX_VFS_SIZE = 1024 * MB; // 1 GB
S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB;
cache_size = llclamp(cache_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE);
- S64 texture_cache_size = cache_size;
+ S64 vfs_size = llmin((S64)((cache_size * 2) / 10), MAX_VFS_SIZE);
+ S64 texture_cache_size = cache_size - vfs_size;
S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);
texture_cache_size -= extra;
+
LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion());
- return true;
+ LLSplashScreen::update(LLTrans::getString("StartupInitializingVFS"));
+
+ // Init the VFS
+ vfs_size = llmin(vfs_size + extra, MAX_VFS_SIZE);
+ vfs_size = (vfs_size / MB) * MB; // make sure it is MB aligned
+ U32 vfs_size_u32 = (U32)vfs_size;
+ U32 old_vfs_size = gSavedSettings.getU32("VFSOldSize") * MB;
+ bool resize_vfs = (vfs_size_u32 != old_vfs_size);
+ if (resize_vfs)
+ {
+ gSavedSettings.setU32("VFSOldSize", vfs_size_u32 / MB);
+ }
+ LL_INFOS("AppCache") << "VFS CACHE SIZE: " << vfs_size / (1024*1024) << " MB" << LL_ENDL;
+
+ // This has to happen BEFORE starting the vfs
+ // time_t ltime;
+ srand(time(NULL)); // Flawfinder: ignore
+ U32 old_salt = gSavedSettings.getU32("VFSSalt");
+ U32 new_salt;
+ std::string old_vfs_data_file;
+ std::string old_vfs_index_file;
+ std::string new_vfs_data_file;
+ std::string new_vfs_index_file;
+ std::string static_vfs_index_file;
+ std::string static_vfs_data_file;
+
+ if (gSavedSettings.getBOOL("AllowMultipleViewers"))
+ {
+ // don't mess with renaming the VFS in this case
+ new_salt = old_salt;
+ }
+ else
+ {
+ do
+ {
+ new_salt = rand();
+ } while(new_salt == old_salt);
+ }
+
+ old_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_DATA_FILE_BASE) + llformat("%u", old_salt);
+
+ // make sure this file exists
+ llstat s;
+ S32 stat_result = LLFile::stat(old_vfs_data_file, &s);
+ if (stat_result)
+ {
+ // doesn't exist, look for a data file
+ std::string mask;
+ mask = VFS_DATA_FILE_BASE;
+ mask += "*";
+
+ std::string dir;
+ dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
+
+ std::string found_file;
+ LLDirIterator iter(dir, mask);
+ if (iter.next(found_file))
+ {
+ old_vfs_data_file = gDirUtilp->add(dir, found_file);
+
+ S32 start_pos = found_file.find_last_of('.');
+ if (start_pos > 0)
+ {
+ sscanf(found_file.substr(start_pos+1).c_str(), "%d", &old_salt);
+ }
+ LL_DEBUGS("AppCache") << "Default vfs data file not present, found: " << old_vfs_data_file << " Old salt: " << old_salt << LL_ENDL;
+ }
+ }
+
+ old_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u", old_salt);
+
+ stat_result = LLFile::stat(old_vfs_index_file, &s);
+ if (stat_result)
+ {
+ // We've got a bad/missing index file, nukem!
+ LL_WARNS("AppCache") << "Bad or missing vfx index file " << old_vfs_index_file << LL_ENDL;
+ LL_WARNS("AppCache") << "Removing old vfs data file " << old_vfs_data_file << LL_ENDL;
+ LLFile::remove(old_vfs_data_file);
+ LLFile::remove(old_vfs_index_file);
+
+ // Just in case, nuke any other old cache files in the directory.
+ std::string dir;
+ dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "");
+
+ std::string mask;
+ mask = VFS_DATA_FILE_BASE;
+ mask += "*";
+
+ gDirUtilp->deleteFilesInDir(dir, mask);
+
+ mask = VFS_INDEX_FILE_BASE;
+ mask += "*";
+
+ gDirUtilp->deleteFilesInDir(dir, mask);
+ }
+
+ new_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_DATA_FILE_BASE) + llformat("%u", new_salt);
+ new_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, VFS_INDEX_FILE_BASE) + llformat("%u", new_salt);
+
+ static_vfs_data_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "static_data.db2");
+ static_vfs_index_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "static_index.db2");
+
+ if (resize_vfs)
+ {
+ LL_DEBUGS("AppCache") << "Removing old vfs and re-sizing" << LL_ENDL;
+
+ LLFile::remove(old_vfs_data_file);
+ LLFile::remove(old_vfs_index_file);
+ }
+ else if (old_salt != new_salt)
+ {
+ // move the vfs files to a new name before opening
+ LL_DEBUGS("AppCache") << "Renaming " << old_vfs_data_file << " to " << new_vfs_data_file << LL_ENDL;
+ LL_DEBUGS("AppCache") << "Renaming " << old_vfs_index_file << " to " << new_vfs_index_file << LL_ENDL;
+ LLFile::rename(old_vfs_data_file, new_vfs_data_file);
+ LLFile::rename(old_vfs_index_file, new_vfs_index_file);
+ }
+
+ // Startup the VFS...
+ gSavedSettings.setU32("VFSSalt", new_salt);
+
+ // Don't remove VFS after viewer crashes. If user has corrupt data, they can reinstall. JC
+ gVFS = LLVFS::createLLVFS(new_vfs_index_file, new_vfs_data_file, false, vfs_size_u32, false);
+ if (!gVFS)
+ {
+ return false;
+ }
+
+ gStaticVFS = LLVFS::createLLVFS(static_vfs_index_file, static_vfs_data_file, true, 0, false);
+ if (!gStaticVFS)
+ {
+ return false;
+ }
+
+ BOOL success = gVFS->isValid() && gStaticVFS->isValid();
+ if (!success)
+ {
+ return false;
+ }
+ else
+ {
+ LLVFile::initClass();
+
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ if (gSavedSettings.getBOOL("DumpVFSCaches"))
+ {
+ dumpVFSCaches();
+ }
+#endif
+
+ return true;
+ }
}
void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb)