DRTVWR-546 merge up to 6.5.2

master
Dave Houlton 2021-12-15 14:37:18 -07:00
commit cf35d27dfb
212 changed files with 3899 additions and 5065 deletions

1
.gitignore vendored
View File

@ -57,6 +57,7 @@ indra/newview/search_history.txt
indra/newview/teleport_history.txt indra/newview/teleport_history.txt
indra/newview/typed_locations.txt indra/newview/typed_locations.txt
indra/newview/vivox-runtime indra/newview/vivox-runtime
indra/newview/skins/default/html/common/equirectangular/js
indra/server-linux-* indra/server-linux-*
indra/temp indra/temp
indra/test/linden_file.dat indra/test/linden_file.dat

View File

@ -367,6 +367,58 @@
<key>version</key> <key>version</key>
<string>2.3.557064</string> <string>2.3.557064</string>
</map> </map>
<key>cubemaptoequirectangular</key>
<map>
<key>copyright</key>
<string>Copyright (c) 2017 Jaume Sanchez Elias, http://www.clicktorelease.com</string>
<key>license</key>
<string>MIT</string>
<key>license_file</key>
<string>LICENSES/CUBEMAPTOEQUIRECTANGULAR_LICENSE.txt</string>
<key>name</key>
<string>cubemaptoequirectangular</string>
<key>platforms</key>
<map>
<key>darwin64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>7e4622b497bc465b01ff6d3e7e0b4214</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89303/815402/cubemaptoequirectangular-1.1.0-darwin64-564841.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>b5ea7097ae10037024b0c2b3df9812b5</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89307/815434/cubemaptoequirectangular-1.1.0-windows-564841.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>ac54672e0b38f52726f5c99047c913e4</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89306/815431/cubemaptoequirectangular-1.1.0-windows64-564841.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>1.1.0</string>
</map>
<key>curl</key> <key>curl</key>
<map> <map>
<key>copyright</key> <key>copyright</key>
@ -1307,6 +1359,58 @@
<key>version</key> <key>version</key>
<string>2012.1-2</string> <string>2012.1-2</string>
</map> </map>
<key>jpegencoderbasic</key>
<map>
<key>copyright</key>
<string>Andreas Ritter, www.bytestrom.eu, 11/2009</string>
<key>license</key>
<string>NONE</string>
<key>license_file</key>
<string>LICENSES/JPEG_ENCODER_BASIC_LICENSE.txt</string>
<key>name</key>
<string>jpegencoderbasic</string>
<key>platforms</key>
<map>
<key>darwin64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>c3c9e60bdc12b35e0e3d6b67d5635f60</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89304/815407/jpegencoderbasic-1.0-darwin64-564842.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>0a376676dbb43fdd0c81ffdfbc5e6f81</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89308/815432/jpegencoderbasic-1.0-windows-564842.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>e70898903475d8ac2e81ff33278fc987</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89309/815433/jpegencoderbasic-1.0-windows64-564842.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>1.0</string>
</map>
<key>jpeglib</key> <key>jpeglib</key>
<map> <map>
<key>copyright</key> <key>copyright</key>
@ -2939,6 +3043,58 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>version</key> <key>version</key>
<string>4.10.0000.32327.5fc3fe7c.558436</string> <string>4.10.0000.32327.5fc3fe7c.558436</string>
</map> </map>
<key>threejs</key>
<map>
<key>copyright</key>
<string>Copyright © 2010-2021 three.js authors</string>
<key>license</key>
<string>MIT</string>
<key>license_file</key>
<string>LICENSES/THREEJS_LICENSE.txt</string>
<key>name</key>
<string>threejs</string>
<key>platforms</key>
<map>
<key>darwin64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>24440e8219e59d81423b68d3be381fef</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89305/815412/threejs-0.132.2-darwin64-564843.tar.bz2</string>
</map>
<key>name</key>
<string>darwin64</string>
</map>
<key>windows</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>e1303fb9f2242a79aee5fd9f97726ace</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89311/815452/threejs-0.132.2-windows-564843.tar.bz2</string>
</map>
<key>name</key>
<string>windows</string>
</map>
<key>windows64</key>
<map>
<key>archive</key>
<map>
<key>hash</key>
<string>46edf0f55417f8ef0d33a5c007bc3644</string>
<key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/89310/815451/threejs-0.132.2-windows64-564843.tar.bz2</string>
</map>
<key>name</key>
<string>windows64</string>
</map>
</map>
<key>version</key>
<string>0.132.2</string>
</map>
<key>tracy</key> <key>tracy</key>
<map> <map>
<key>canonical_repo</key> <key>canonical_repo</key>
@ -3142,9 +3298,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key> <key>archive</key>
<map> <map>
<key>hash</key> <key>hash</key>
<string>97fac6d88480445c856083ed20d78093</string> <string>a3c8357a2f5a62cd7de43181b02553bc</string>
<key>url</key> <key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/85206/790666/viewer_manager-2.0.562101-darwin64-562101.tar.bz2</string> <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/91396/829032/viewer_manager-2.0.566227-darwin64-566227.tar.bz2</string>
</map> </map>
<key>name</key> <key>name</key>
<string>darwin64</string> <string>darwin64</string>
@ -3166,9 +3322,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>archive</key> <key>archive</key>
<map> <map>
<key>hash</key> <key>hash</key>
<string>3f6271ec0e2e2f0cc1067d4c4102bb4c</string> <string>0654b449d9bdf3507664cf5caa67336f</string>
<key>url</key> <key>url</key>
<string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/85208/790681/viewer_manager-2.0.562101-windows-562101.tar.bz2</string> <string>https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/91397/829041/viewer_manager-2.0.566227-windows-566227.tar.bz2</string>
</map> </map>
<key>name</key> <key>name</key>
<string>windows</string> <string>windows</string>
@ -3179,7 +3335,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
<key>source_type</key> <key>source_type</key>
<string>hg</string> <string>hg</string>
<key>version</key> <key>version</key>
<string>2.0.562101</string> <string>2.0.566227</string>
</map> </map>
<key>vlc-bin</key> <key>vlc-bin</key>
<map> <map>

View File

@ -226,8 +226,15 @@ Ansariel Hiller
SL-13364 SL-13364
SL-13858 SL-13858
SL-13697 SL-13697
SL-14939
SL-14940
SL-14941
SL-13395 SL-13395
SL-3136 SL-3136
SL-15200
SL-15226
SL-15227
SL-15398
Aralara Rajal Aralara Rajal
Arare Chantilly Arare Chantilly
CHUIBUG-191 CHUIBUG-191

View File

@ -42,7 +42,7 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llmeshoptimizer)
add_subdirectory(${LIBS_OPEN_PREFIX}llmessage) add_subdirectory(${LIBS_OPEN_PREFIX}llmessage)
add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive) add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive)
add_subdirectory(${LIBS_OPEN_PREFIX}llrender) add_subdirectory(${LIBS_OPEN_PREFIX}llrender)
add_subdirectory(${LIBS_OPEN_PREFIX}llvfs) add_subdirectory(${LIBS_OPEN_PREFIX}llfilesystem)
add_subdirectory(${LIBS_OPEN_PREFIX}llwindow) add_subdirectory(${LIBS_OPEN_PREFIX}llwindow)
add_subdirectory(${LIBS_OPEN_PREFIX}llxml) add_subdirectory(${LIBS_OPEN_PREFIX}llxml)

View File

@ -70,7 +70,6 @@ if (WINDOWS)
if( ADDRESS_SIZE EQUAL 32 ) if( ADDRESS_SIZE EQUAL 32 )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64")
endif() endif()
# Preserve first-pass-through versions (ie no FORCE overwrite). Prevents recursive addition of /Zo (04/2021) # Preserve first-pass-through versions (ie no FORCE overwrite). Prevents recursive addition of /Zo (04/2021)
set(OG_CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} CACHE STRING "OG_CXX_FLAGS_RELEASE") set(OG_CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} CACHE STRING "OG_CXX_FLAGS_RELEASE")
set(OG_CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} CACHE STRING "OG_CXX_FLAGS_RELWITHDEBINFO") set(OG_CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} CACHE STRING "OG_CXX_FLAGS_RELWITHDEBINFO")

View File

@ -67,7 +67,7 @@ set(cmake_SOURCE_FILES
LLSharedLibs.cmake LLSharedLibs.cmake
LLTestCommand.cmake LLTestCommand.cmake
LLUI.cmake LLUI.cmake
LLVFS.cmake LLFileSystem.cmake
LLWindow.cmake LLWindow.cmake
LLXML.cmake LLXML.cmake
Linking.cmake Linking.cmake

View File

@ -0,0 +1,5 @@
# -*- cmake -*-
use_prebuilt_binary(cubemaptoequirectangular)
# Main JS file
configure_file("${AUTOBUILD_INSTALL_DIR}/js/CubemapToEquirectangular.js" "${CMAKE_SOURCE_DIR}/newview/skins/default/html/common/equirectangular/js/CubemapToEquirectangular.js" COPYONLY)

View File

@ -0,0 +1,5 @@
# -*- cmake -*-
use_prebuilt_binary(jpegencoderbasic)
# Main JS file
configure_file("${AUTOBUILD_INSTALL_DIR}/js/jpeg_encoder_basic.js" "${CMAKE_SOURCE_DIR}/newview/skins/default/html/common/equirectangular/js/jpeg_encoder_basic.js" COPYONLY)

View File

@ -0,0 +1,7 @@
# -*- cmake -*-
set(LLFILESYSTEM_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llfilesystem
)
set(LLFILESYSTEM_LIBRARIES llfilesystem)

View File

@ -1,7 +0,0 @@
# -*- cmake -*-
set(LLVFS_INCLUDE_DIRS
${LIBS_OPEN_DIR}/llvfs
)
set(LLVFS_LIBRARIES llvfs)

View File

@ -0,0 +1,8 @@
# -*- cmake -*-
use_prebuilt_binary(threejs)
# Main three.js file
configure_file("${AUTOBUILD_INSTALL_DIR}/js/three.min.js" "${CMAKE_SOURCE_DIR}/newview/skins/default/html/common/equirectangular/js/three.min.js" COPYONLY)
# Controls to move around the scene using mouse or keyboard
configure_file("${AUTOBUILD_INSTALL_DIR}/js/OrbitControls.js" "${CMAKE_SOURCE_DIR}/newview/skins/default/html/common/equirectangular/js/OrbitControls.js" COPYONLY)

View File

@ -10,11 +10,11 @@ include(LLImage)
include(LLMath) include(LLMath)
include(LLImageJ2COJ) include(LLImageJ2COJ)
include(LLKDU) include(LLKDU)
include(LLVFS) include(LLFileSystem)
include_directories( include_directories(
${LLCOMMON_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${LLIMAGE_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
) )
@ -66,7 +66,7 @@ endif (DARWIN)
target_link_libraries(llimage_libtest target_link_libraries(llimage_libtest
${LEGACY_STDIO_LIBS} ${LEGACY_STDIO_LIBS}
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLIMAGE_LIBRARIES} ${LLIMAGE_LIBRARIES}
${LLKDU_LIBRARIES} ${LLKDU_LIBRARIES}

View File

@ -16,7 +16,7 @@ include(LLMessage)
include(LLRender) include(LLRender)
include(LLWindow) include(LLWindow)
include(LLUI) include(LLUI)
include(LLVFS) # ugh, needed for LLDir include(LLFileSystem)
include(LLXML) include(LLXML)
include(Hunspell) include(Hunspell)
include(Linking) include(Linking)
@ -29,7 +29,7 @@ include_directories(
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS}
${LLUI_INCLUDE_DIRS} ${LLUI_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS}
${LIBS_PREBUILD_DIR}/include/hunspell ${LIBS_PREBUILD_DIR}/include/hunspell

View File

@ -9,7 +9,7 @@ include(LLCommon)
include(LLCrashLogger) include(LLCrashLogger)
include(LLMath) include(LLMath)
include(LLMessage) include(LLMessage)
include(LLVFS) include(LLFileSystem)
include(LLXML) include(LLXML)
include(Linking) include(Linking)
include(UI) include(UI)
@ -21,7 +21,7 @@ include_directories(
${LLCOMMON_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS}
${LLCRASHLOGGER_INCLUDE_DIRS} ${LLCRASHLOGGER_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS}
${FREETYPE_INCLUDE_DIRS} ${FREETYPE_INCLUDE_DIRS}
) )
@ -62,10 +62,9 @@ set(LIBRT_LIBRARY rt)
target_link_libraries(linux-crash-logger target_link_libraries(linux-crash-logger
${LLCRASHLOGGER_LIBRARIES} ${LLCRASHLOGGER_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
${LLMESSAGE_LIBRARIES} ${LLMESSAGE_LIBRARIES}
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLCOREHTTP_LIBRARIES} ${LLCOREHTTP_LIBRARIES}
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}

View File

@ -11,7 +11,7 @@ include(LLMath)
include(LLMessage) include(LLMessage)
include(LLCoreHttp) include(LLCoreHttp)
include(LLRender) include(LLRender)
include(LLVFS) include(LLFileSystem)
include(LLWindow) include(LLWindow)
include(LLXML) include(LLXML)
include(Linking) include(Linking)
@ -23,7 +23,7 @@ include_directories(
${LLINVENTORY_INCLUDE_DIRS} ${LLINVENTORY_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS}
) )
@ -83,7 +83,7 @@ target_link_libraries(llappearance
${LLINVENTORY_LIBRARIES} ${LLINVENTORY_LIBRARIES}
${LLIMAGE_LIBRARIES} ${LLIMAGE_LIBRARIES}
${LLRENDER_LIBRARIES} ${LLRENDER_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
@ -100,7 +100,7 @@ if (BUILD_HEADLESS)
${LLINVENTORY_LIBRARIES} ${LLINVENTORY_LIBRARIES}
${LLIMAGE_LIBRARIES} ${LLIMAGE_LIBRARIES}
${LLRENDERHEADLESS_LIBRARIES} ${LLRENDERHEADLESS_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
@ -109,15 +109,3 @@ if (BUILD_HEADLESS)
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
) )
endif (BUILD_HEADLESS) endif (BUILD_HEADLESS)
#add unit tests
#if (LL_TESTS)
# INCLUDE(LLAddBuildTest)
# SET(llappearance_TEST_SOURCE_FILES
# # no real unit tests yet!
# )
# LL_ADD_PROJECT_UNIT_TESTS(llappearance "${llappearance_TEST_SOURCE_FILES}")
#set(TEST_DEBUG on)
# set(test_libs llappearance ${LLCOMMON_LIBRARIES})
#endif (LL_TESTS)

View File

@ -33,8 +33,6 @@
#include "llimagej2c.h" #include "llimagej2c.h"
#include "llimagetga.h" #include "llimagetga.h"
#include "lldir.h" #include "lldir.h"
#include "llvfile.h"
#include "llvfs.h"
#include "lltexlayerparams.h" #include "lltexlayerparams.h"
#include "lltexturemanagerbridge.h" #include "lltexturemanagerbridge.h"
#include "lllocaltextureobject.h" #include "lllocaltextureobject.h"

View File

@ -9,14 +9,14 @@ include(OPENAL)
include(LLCommon) include(LLCommon)
include(LLMath) include(LLMath)
include(LLMessage) include(LLMessage)
include(LLVFS) include(LLFileSystem)
include_directories( include_directories(
${LLAUDIO_INCLUDE_DIRS} ${LLAUDIO_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${OGG_INCLUDE_DIRS} ${OGG_INCLUDE_DIRS}
${VORBISENC_INCLUDE_DIRS} ${VORBISENC_INCLUDE_DIRS}
${VORBISFILE_INCLUDE_DIRS} ${VORBISFILE_INCLUDE_DIRS}
@ -86,7 +86,7 @@ target_link_libraries(
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLMESSAGE_LIBRARIES} ${LLMESSAGE_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${VORBISENC_LIBRARIES} ${VORBISENC_LIBRARIES}
${VORBISFILE_LIBRARIES} ${VORBISFILE_LIBRARIES}
${VORBIS_LIBRARIES} ${VORBIS_LIBRARIES}

View File

@ -29,7 +29,7 @@
#include "llaudioengine.h" #include "llaudioengine.h"
#include "lllfsthread.h" #include "lllfsthread.h"
#include "llvfile.h" #include "llfilesystem.h"
#include "llstring.h" #include "llstring.h"
#include "lldir.h" #include "lldir.h"
#include "llendianswizzle.h" #include "llendianswizzle.h"
@ -90,19 +90,17 @@ protected:
LLUUID mUUID; LLUUID mUUID;
std::vector<U8> mWAVBuffer; std::vector<U8> mWAVBuffer;
#if !defined(USE_WAV_VFILE)
std::string mOutFilename; std::string mOutFilename;
LLLFSThread::handle_t mFileHandle; LLLFSThread::handle_t mFileHandle;
#endif
LLVFile *mInFilep; LLFileSystem *mInFilep;
OggVorbis_File mVF; OggVorbis_File mVF;
S32 mCurrentSection; S32 mCurrentSection;
}; };
size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource) size_t cache_read(void *ptr, size_t size, size_t nmemb, void *datasource)
{ {
LLVFile *file = (LLVFile *)datasource; LLFileSystem *file = (LLFileSystem *)datasource;
if (file->read((U8*)ptr, (S32)(size * nmemb))) /*Flawfinder: ignore*/ if (file->read((U8*)ptr, (S32)(size * nmemb))) /*Flawfinder: ignore*/
{ {
@ -115,11 +113,11 @@ size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource)
} }
} }
S32 vfs_seek(void *datasource, ogg_int64_t offset, S32 whence) S32 cache_seek(void *datasource, ogg_int64_t offset, S32 whence)
{ {
LLVFile *file = (LLVFile *)datasource; LLFileSystem *file = (LLFileSystem *)datasource;
// vfs has 31-bit files // cache has 31-bit files
if (offset > S32_MAX) if (offset > S32_MAX)
{ {
return -1; return -1;
@ -137,7 +135,7 @@ S32 vfs_seek(void *datasource, ogg_int64_t offset, S32 whence)
origin = -1; origin = -1;
break; break;
default: default:
LL_ERRS("AudioEngine") << "Invalid whence argument to vfs_seek" << LL_ENDL; LL_ERRS("AudioEngine") << "Invalid whence argument to cache_seek" << LL_ENDL;
return -1; return -1;
} }
@ -151,16 +149,16 @@ S32 vfs_seek(void *datasource, ogg_int64_t offset, S32 whence)
} }
} }
S32 vfs_close (void *datasource) S32 cache_close (void *datasource)
{ {
LLVFile *file = (LLVFile *)datasource; LLFileSystem *file = (LLFileSystem *)datasource;
delete file; delete file;
return 0; return 0;
} }
long vfs_tell (void *datasource) long cache_tell (void *datasource)
{ {
LLVFile *file = (LLVFile *)datasource; LLFileSystem *file = (LLFileSystem *)datasource;
return file->tell(); return file->tell();
} }
@ -172,11 +170,10 @@ LLVorbisDecodeState::LLVorbisDecodeState(const LLUUID &uuid, const std::string &
mUUID = uuid; mUUID = uuid;
mInFilep = NULL; mInFilep = NULL;
mCurrentSection = 0; mCurrentSection = 0;
#if !defined(USE_WAV_VFILE)
mOutFilename = out_filename; mOutFilename = out_filename;
mFileHandle = LLLFSThread::nullHandle(); mFileHandle = LLLFSThread::nullHandle();
#endif
// No default value for mVF, it's an ogg structure? // No default value for mVF, it's an ogg structure?
// Hey, let's zero it anyway, for predictability. // Hey, let's zero it anyway, for predictability.
memset(&mVF, 0, sizeof(mVF)); memset(&mVF, 0, sizeof(mVF));
} }
@ -193,15 +190,15 @@ LLVorbisDecodeState::~LLVorbisDecodeState()
BOOL LLVorbisDecodeState::initDecode() BOOL LLVorbisDecodeState::initDecode()
{ {
ov_callbacks vfs_callbacks; ov_callbacks cache_callbacks;
vfs_callbacks.read_func = vfs_read; cache_callbacks.read_func = cache_read;
vfs_callbacks.seek_func = vfs_seek; cache_callbacks.seek_func = cache_seek;
vfs_callbacks.close_func = vfs_close; cache_callbacks.close_func = cache_close;
vfs_callbacks.tell_func = vfs_tell; cache_callbacks.tell_func = cache_tell;
LL_DEBUGS("AudioEngine") << "Initing decode from vfile: " << mUUID << LL_ENDL; LL_DEBUGS("AudioEngine") << "Initing decode from vfile: " << mUUID << LL_ENDL;
mInFilep = new LLVFile(gVFS, mUUID, LLAssetType::AT_SOUND); mInFilep = new LLFileSystem(mUUID, LLAssetType::AT_SOUND);
if (!mInFilep || !mInFilep->getSize()) if (!mInFilep || !mInFilep->getSize())
{ {
LL_WARNS("AudioEngine") << "unable to open vorbis source vfile for reading" << LL_ENDL; LL_WARNS("AudioEngine") << "unable to open vorbis source vfile for reading" << LL_ENDL;
@ -210,7 +207,7 @@ BOOL LLVorbisDecodeState::initDecode()
return FALSE; return FALSE;
} }
S32 r = ov_open_callbacks(mInFilep, &mVF, NULL, 0, vfs_callbacks); S32 r = ov_open_callbacks(mInFilep, &mVF, NULL, 0, cache_callbacks);
if(r < 0) if(r < 0)
{ {
LL_WARNS("AudioEngine") << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << mUUID << LL_ENDL; LL_WARNS("AudioEngine") << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << mUUID << LL_ENDL;
@ -370,7 +367,7 @@ BOOL LLVorbisDecodeState::decodeSection()
{ {
if (!mInFilep) if (!mInFilep)
{ {
LL_WARNS("AudioEngine") << "No VFS file to decode in vorbis!" << LL_ENDL; LL_WARNS("AudioEngine") << "No cache file to decode in vorbis!" << LL_ENDL;
return TRUE; return TRUE;
} }
if (mDone) if (mDone)
@ -420,9 +417,7 @@ BOOL LLVorbisDecodeState::finishDecode()
return TRUE; // We've finished return TRUE; // We've finished
} }
#if !defined(USE_WAV_VFILE)
if (mFileHandle == LLLFSThread::nullHandle()) if (mFileHandle == LLLFSThread::nullHandle())
#endif
{ {
ov_clear(&mVF); ov_clear(&mVF);
@ -495,11 +490,9 @@ BOOL LLVorbisDecodeState::finishDecode()
mValid = FALSE; mValid = FALSE;
return TRUE; // we've finished return TRUE; // we've finished
} }
#if !defined(USE_WAV_VFILE)
mBytesRead = -1; mBytesRead = -1;
mFileHandle = LLLFSThread::sLocal->write(mOutFilename, &mWAVBuffer[0], 0, mWAVBuffer.size(), mFileHandle = LLLFSThread::sLocal->write(mOutFilename, &mWAVBuffer[0], 0, mWAVBuffer.size(),
new WriteResponder(this)); new WriteResponder(this));
#endif
} }
if (mFileHandle != LLLFSThread::nullHandle()) if (mFileHandle != LLLFSThread::nullHandle())
@ -521,11 +514,6 @@ BOOL LLVorbisDecodeState::finishDecode()
mDone = TRUE; mDone = TRUE;
#if defined(USE_WAV_VFILE)
// write the data.
LLVFile output(gVFS, mUUID, LLAssetType::AT_SOUND_WAV);
output.write(&mWAVBuffer[0], mWAVBuffer.size());
#endif
LL_DEBUGS("AudioEngine") << "Finished decode for " << getUUID() << LL_ENDL; LL_DEBUGS("AudioEngine") << "Finished decode for " << getUUID() << LL_ENDL;
return TRUE; return TRUE;
@ -535,7 +523,7 @@ void LLVorbisDecodeState::flushBadFile()
{ {
if (mInFilep) if (mInFilep)
{ {
LL_WARNS("AudioEngine") << "Flushing bad vorbis file from VFS for " << mUUID << LL_ENDL; LL_WARNS("AudioEngine") << "Flushing bad vorbis file from cache for " << mUUID << LL_ENDL;
mInFilep->remove(); mInFilep->remove();
} }
} }

View File

@ -33,7 +33,6 @@
#include "llassettype.h" #include "llassettype.h"
#include "llframetimer.h" #include "llframetimer.h"
class LLVFS;
class LLVorbisDecodeState; class LLVorbisDecodeState;
class LLAudioDecodeMgr class LLAudioDecodeMgr

View File

@ -35,7 +35,7 @@
#include "sound_ids.h" // temporary hack for min/max distances #include "sound_ids.h" // temporary hack for min/max distances
#include "llvfs.h" #include "llfilesystem.h"
#include "lldir.h" #include "lldir.h"
#include "llaudiodecodemgr.h" #include "llaudiodecodemgr.h"
#include "llassetstorage.h" #include "llassetstorage.h"
@ -684,13 +684,9 @@ bool LLAudioEngine::preloadSound(const LLUUID &uuid)
return true; return true;
} }
// At some point we need to have the audio/asset system check the static VFS
// before it goes off and fetches stuff from the server.
//LL_WARNS() << "Used internal preload for non-local sound" << LL_ENDL;
return false; return false;
} }
bool LLAudioEngine::isWindEnabled() bool LLAudioEngine::isWindEnabled()
{ {
return mEnableWind; return mEnableWind;
@ -1018,13 +1014,12 @@ bool LLAudioEngine::hasDecodedFile(const LLUUID &uuid)
bool LLAudioEngine::hasLocalFile(const LLUUID &uuid) bool LLAudioEngine::hasLocalFile(const LLUUID &uuid)
{ {
// See if it's in the VFS. // See if it's in the cache.
bool have_local = gVFS->getExists(uuid, LLAssetType::AT_SOUND); bool have_local = LLFileSystem::getExists(uuid, LLAssetType::AT_SOUND);
LL_DEBUGS("AudioEngine") << "sound uuid "<<uuid<<" exists in VFS"<<LL_ENDL; LL_DEBUGS("AudioEngine") << "sound uuid " << uuid << " exists in cache" << LL_ENDL;
return have_local; return have_local;
} }
void LLAudioEngine::startNextTransfer() void LLAudioEngine::startNextTransfer()
{ {
//LL_INFOS() << "LLAudioEngine::startNextTransfer()" << LL_ENDL; //LL_INFOS() << "LLAudioEngine::startNextTransfer()" << LL_ENDL;
@ -1225,7 +1220,7 @@ void LLAudioEngine::startNextTransfer()
// static // static
void LLAudioEngine::assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status) void LLAudioEngine::assetCallback(const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status)
{ {
if (!gAudiop) if (!gAudiop)
{ {

View File

@ -50,15 +50,6 @@ const F32 DEFAULT_MIN_DISTANCE = 2.0f;
#define MAX_CHANNELS 30 #define MAX_CHANNELS 30
#define MAX_BUFFERS 40 // Some extra for preloading, maybe? #define MAX_BUFFERS 40 // Some extra for preloading, maybe?
// This define is intended to allow us to switch from os based wav
// file loading to vfs based wav file loading. The problem is that I
// am unconvinced that the LLWaveFile works for loading sounds from
// memory. So, until that is fixed up, changed, whatever, this remains
// undefined.
//#define USE_WAV_VFILE
class LLVFS;
class LLAudioSource; class LLAudioSource;
class LLAudioData; class LLAudioData;
class LLAudioChannel; class LLAudioChannel;
@ -67,11 +58,9 @@ class LLAudioBuffer;
class LLStreamingAudioInterface; class LLStreamingAudioInterface;
struct SoundData; struct SoundData;
// //
// LLAudioEngine definition // LLAudioEngine definition
// //
class LLAudioEngine class LLAudioEngine
{ {
friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods. friend class LLAudioChannelOpenAL; // bleh. channel needs some listener methods.
@ -182,7 +171,7 @@ public:
// Asset callback when we're retrieved a sound from the asset server. // Asset callback when we're retrieved a sound from the asset server.
void startNextTransfer(); void startNextTransfer();
static void assetCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status); static void assetCallback(const LLUUID &uuid, LLAssetType::EType type, void *user_data, S32 result_code, LLExtStat ext_status);
friend class LLPipeline; // For debugging friend class LLPipeline; // For debugging
public: public:

View File

@ -6,14 +6,14 @@ include(00-Common)
include(LLCommon) include(LLCommon)
include(LLMath) include(LLMath)
include(LLMessage) include(LLMessage)
include(LLVFS) include(LLFileSystem)
include(LLXML) include(LLXML)
include_directories( include_directories(
${LLCOMMON_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS}
) )
include_directories(SYSTEM include_directories(SYSTEM
@ -85,18 +85,6 @@ target_link_libraries(
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLMESSAGE_LIBRARIES} ${LLMESSAGE_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
) )
# Add tests
#if (LL_TESTS)
# include(LLAddBuildTest)
# # UNIT TESTS
# SET(llcharacter_TEST_SOURCE_FILES
# lljoint.cpp
# )
# LL_ADD_PROJECT_UNIT_TESTS(llcharacter "${llcharacter_TEST_SOURCE_FILES}")
#endif (LL_TESTS)

View File

@ -70,6 +70,11 @@ LLMotion::LLMotionInitStatus LLKeyframeFallMotion::onInitialize(LLCharacter *cha
// load keyframe data, setup pose and joint states // load keyframe data, setup pose and joint states
LLMotion::LLMotionInitStatus result = LLKeyframeMotion::onInitialize(character); LLMotion::LLMotionInitStatus result = LLKeyframeMotion::onInitialize(character);
if (result != LLMotion::STATUS_SUCCESS)
{
return result;
}
for (U32 jm=0; jm<mJointMotionList->getNumJointMotions(); jm++) for (U32 jm=0; jm<mJointMotionList->getNumJointMotions(); jm++)
{ {
if (!mJointStates[jm]->getJoint()) if (!mJointStates[jm]->getJoint())

View File

@ -39,14 +39,13 @@
#include "llendianswizzle.h" #include "llendianswizzle.h"
#include "llkeyframemotion.h" #include "llkeyframemotion.h"
#include "llquantize.h" #include "llquantize.h"
#include "llvfile.h"
#include "m3math.h" #include "m3math.h"
#include "message.h" #include "message.h"
#include "llfilesystem.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Static Definitions // Static Definitions
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LLVFS* LLKeyframeMotion::sVFS = NULL;
LLKeyframeDataCache::keyframe_data_map_t LLKeyframeDataCache::sKeyframeDataMap; LLKeyframeDataCache::keyframe_data_map_t LLKeyframeDataCache::sKeyframeDataMap;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -515,7 +514,7 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
return STATUS_SUCCESS; return STATUS_SUCCESS;
default: default:
// we don't know what state the asset is in yet, so keep going // we don't know what state the asset is in yet, so keep going
// check keyframe cache first then static vfs then asset request // check keyframe cache first then file cache then asset request
break; break;
} }
@ -559,13 +558,8 @@ LLMotion::LLMotionInitStatus LLKeyframeMotion::onInitialize(LLCharacter *charact
U8 *anim_data; U8 *anim_data;
S32 anim_file_size; S32 anim_file_size;
if (!sVFS)
{
LL_ERRS() << "Must call LLKeyframeMotion::setVFS() first before loading a keyframe file!" << LL_ENDL;
}
BOOL success = FALSE; BOOL success = FALSE;
LLVFile* anim_file = new LLVFile(sVFS, mID, LLAssetType::AT_ANIMATION); LLFileSystem* anim_file = new LLFileSystem(mID, LLAssetType::AT_ANIMATION);
if (!anim_file || !anim_file->getSize()) if (!anim_file || !anim_file->getSize())
{ {
delete anim_file; delete anim_file;
@ -2297,10 +2291,9 @@ void LLKeyframeMotion::setLoopOut(F32 out_point)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// onLoadComplete() // onLoadComplete()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void LLKeyframeMotion::onLoadComplete(LLVFS *vfs, void LLKeyframeMotion::onLoadComplete(const LLUUID& asset_uuid,
const LLUUID& asset_uuid, LLAssetType::EType type,
LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status)
void* user_data, S32 status, LLExtStat ext_status)
{ {
LLUUID* id = (LLUUID*)user_data; LLUUID* id = (LLUUID*)user_data;
@ -2332,7 +2325,7 @@ void LLKeyframeMotion::onLoadComplete(LLVFS *vfs,
// asset already loaded // asset already loaded
return; return;
} }
LLVFile file(vfs, asset_uuid, type, LLVFile::READ); LLFileSystem file(asset_uuid, type, LLFileSystem::READ);
S32 size = file.getSize(); S32 size = file.getSize();
U8* buffer = new U8[size]; U8* buffer = new U8[size];

View File

@ -44,7 +44,6 @@
#include "llbvhconsts.h" #include "llbvhconsts.h"
class LLKeyframeDataCache; class LLKeyframeDataCache;
class LLVFS;
class LLDataPacker; class LLDataPacker;
#define MIN_REQUIRED_PIXEL_AREA_KEYFRAME (40.f) #define MIN_REQUIRED_PIXEL_AREA_KEYFRAME (40.f)
@ -141,10 +140,7 @@ public:
virtual void setStopTime(F32 time); virtual void setStopTime(F32 time);
static void setVFS(LLVFS* vfs) { sVFS = vfs; } static void onLoadComplete(const LLUUID& asset_uuid,
static void onLoadComplete(LLVFS *vfs,
const LLUUID& asset_uuid,
LLAssetType::EType type, LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status); void* user_data, S32 status, LLExtStat ext_status);
@ -416,13 +412,7 @@ public:
U32 getNumJointMotions() const { return mJointMotionArray.size(); } U32 getNumJointMotions() const { return mJointMotionArray.size(); }
}; };
protected: protected:
static LLVFS* sVFS;
//-------------------------------------------------------------------------
// Member Data
//-------------------------------------------------------------------------
JointMotionList* mJointMotionList; JointMotionList* mJointMotionList;
std::vector<LLPointer<LLJointState> > mJointStates; std::vector<LLPointer<LLJointState> > mJointStates;
LLJoint* mPelvisp; LLJoint* mPelvisp;

View File

@ -106,7 +106,8 @@ BOOL LLApp::sDisableCrashlogger = FALSE;
BOOL LLApp::sLogInSignal = FALSE; BOOL LLApp::sLogInSignal = FALSE;
// static // static
LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status // Keeps track of application status
LLScalarCond<LLApp::EAppStatus> LLApp::sStatus{LLApp::APP_STATUS_STOPPED};
LLAppErrorHandler LLApp::sErrorHandler = NULL; LLAppErrorHandler LLApp::sErrorHandler = NULL;
BOOL LLApp::sErrorThreadRunning = FALSE; BOOL LLApp::sErrorThreadRunning = FALSE;
@ -452,7 +453,8 @@ static std::map<LLApp::EAppStatus, const char*> statusDesc
// static // static
void LLApp::setStatus(EAppStatus status) void LLApp::setStatus(EAppStatus status)
{ {
sStatus = status; // notify everyone waiting on sStatus any time its value changes
sStatus.set_all(status);
// This can also happen very late in the application lifecycle -- don't // This can also happen very late in the application lifecycle -- don't
// resurrect a deleted LLSingleton // resurrect a deleted LLSingleton
@ -514,28 +516,28 @@ void LLApp::setStopped()
// static // static
bool LLApp::isStopped() bool LLApp::isStopped()
{ {
return (APP_STATUS_STOPPED == sStatus); return (APP_STATUS_STOPPED == sStatus.get());
} }
// static // static
bool LLApp::isRunning() bool LLApp::isRunning()
{ {
return (APP_STATUS_RUNNING == sStatus); return (APP_STATUS_RUNNING == sStatus.get());
} }
// static // static
bool LLApp::isError() bool LLApp::isError()
{ {
return (APP_STATUS_ERROR == sStatus); return (APP_STATUS_ERROR == sStatus.get());
} }
// static // static
bool LLApp::isQuitting() bool LLApp::isQuitting()
{ {
return (APP_STATUS_QUITTING == sStatus); return (APP_STATUS_QUITTING == sStatus.get());
} }
// static // static

View File

@ -28,9 +28,11 @@
#define LL_LLAPP_H #define LL_LLAPP_H
#include <map> #include <map>
#include "llcond.h"
#include "llrun.h" #include "llrun.h"
#include "llsd.h" #include "llsd.h"
#include <atomic> #include <atomic>
#include <chrono>
// Forward declarations // Forward declarations
class LLErrorThread; class LLErrorThread;
class LLLiveFile; class LLLiveFile;
@ -207,6 +209,36 @@ public:
static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not) static bool isExiting(); // Either quitting or error (app is exiting, cleanly or not)
static int getPid(); static int getPid();
//
// Sleep for specified time while still running
//
// For use by a coroutine or thread that performs some maintenance on a
// periodic basis. (See also LLEventTimer.) This method supports the
// pattern of an "infinite" loop that sleeps for some time, performs some
// action, then sleeps again. The trouble with literally sleeping a worker
// thread is that it could potentially sleep right through attempted
// application shutdown. This method avoids that by returning false as
// soon as the application status changes away from APP_STATUS_RUNNING
// (isRunning()).
//
// sleep() returns true if it sleeps undisturbed for the entire specified
// duration. The idea is that you can code 'while sleep(duration) ...',
// which will break the loop once shutdown begins.
//
// Since any time-based LLUnit should be implicitly convertible to
// F32Milliseconds, accept that specific type as a proxy.
static bool sleep(F32Milliseconds duration);
// Allow any duration defined in terms of <chrono>.
// One can imagine a wonderfully general bidirectional conversion system
// between any type derived from LLUnits::LLUnit<T, LLUnits::Seconds> and
// any std::chrono::duration -- but that doesn't yet exist.
template <typename Rep, typename Period>
bool sleep(const std::chrono::duration<Rep, Period>& duration)
{
// wait_for_unequal() has the opposite bool return convention
return ! sStatus.wait_for_unequal(duration, APP_STATUS_RUNNING);
}
/** @name Error handling methods */ /** @name Error handling methods */
//@{ //@{
/** /**
@ -236,8 +268,8 @@ public:
// Return the Google Breakpad minidump filename after a crash. // Return the Google Breakpad minidump filename after a crash.
char *getMiniDumpFilename() { return mMinidumpPath; } char *getMiniDumpFilename() { return mMinidumpPath; }
std::string* getStaticDebugFile() { return &mStaticDebugFileName; } std::string* getStaticDebugFile() { return &mStaticDebugFileName; }
std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; } std::string* getDynamicDebugFile() { return &mDynamicDebugFileName; }
// Write out a Google Breakpad minidump file. // Write out a Google Breakpad minidump file.
void writeMiniDump(); void writeMiniDump();
@ -265,7 +297,7 @@ public:
protected: protected:
static void setStatus(EAppStatus status); // Use this to change the application status. static void setStatus(EAppStatus status); // Use this to change the application status.
static EAppStatus sStatus; // Reflects current application status static LLScalarCond<EAppStatus> sStatus; // Reflects current application status
static BOOL sErrorThreadRunning; // Set while the error thread is running static BOOL sErrorThreadRunning; // Set while the error thread is running
static BOOL sDisableCrashlogger; // Let the OS handle crashes for us. static BOOL sDisableCrashlogger; // Let the OS handle crashes for us.
std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting. std::wstring mCrashReportPipeStr; //Name of pipe to use for crash reporting.

View File

@ -197,13 +197,37 @@ namespace {
return LLError::getEnabledLogTypesMask() & 0x04; return LLError::getEnabledLogTypesMask() & 0x04;
} }
LL_FORCE_INLINE std::string createBoldANSI()
{
std::string ansi_code;
ansi_code += '\033';
ansi_code += "[";
ansi_code += "1";
ansi_code += "m";
return ansi_code;
}
LL_FORCE_INLINE std::string createResetANSI()
{
std::string ansi_code;
ansi_code += '\033';
ansi_code += "[";
ansi_code += "0";
ansi_code += "m";
return ansi_code;
}
LL_FORCE_INLINE std::string createANSI(const std::string& color) LL_FORCE_INLINE std::string createANSI(const std::string& color)
{ {
std::string ansi_code; std::string ansi_code;
ansi_code += '\033'; ansi_code += '\033';
ansi_code += "["; ansi_code += "[";
ansi_code += "38;5;";
ansi_code += color; ansi_code += color;
ansi_code += "m"; ansi_code += "m";
return ansi_code; return ansi_code;
} }
@ -211,9 +235,26 @@ namespace {
const std::string& message) override const std::string& message) override
{ {
LL_PROFILE_ZONE_SCOPED LL_PROFILE_ZONE_SCOPED
static std::string s_ansi_error = createANSI("31"); // red // The default colors for error, warn and debug are now a bit more pastel
static std::string s_ansi_warn = createANSI("34"); // blue // and easier to read on the default (black) terminal background but you
static std::string s_ansi_debug = createANSI("35"); // magenta // now have the option to set the color of each via an environment variables:
// LL_ANSI_ERROR_COLOR_CODE (default is red)
// LL_ANSI_WARN_COLOR_CODE (default is blue)
// LL_ANSI_DEBUG_COLOR_CODE (default is magenta)
// The list of color codes can be found in many places but I used this page:
// https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#256-colors
// (Note: you may need to restart Visual Studio to pick environment changes)
char* val = nullptr;
std::string s_ansi_error_code = "160";
if ((val = getenv("LL_ANSI_ERROR_COLOR_CODE")) != nullptr) s_ansi_error_code = std::string(val);
std::string s_ansi_warn_code = "33";
if ((val = getenv("LL_ANSI_WARN_COLOR_CODE")) != nullptr) s_ansi_warn_code = std::string(val);
std::string s_ansi_debug_code = "177";
if ((val = getenv("LL_ANSI_DEBUG_COLOR_CODE")) != nullptr) s_ansi_debug_code = std::string(val);
static std::string s_ansi_error = createANSI(s_ansi_error_code); // default is red
static std::string s_ansi_warn = createANSI(s_ansi_warn_code); // default is blue
static std::string s_ansi_debug = createANSI(s_ansi_debug_code); // default is magenta
if (mUseANSI) if (mUseANSI)
{ {
@ -224,7 +265,7 @@ namespace {
else else
{ {
LL_PROFILE_ZONE_NAMED("fprintf"); LL_PROFILE_ZONE_NAMED("fprintf");
fprintf(stderr, "%s\n", message.c_str()); fprintf(stderr, "%s\n", message.c_str());
} }
} }
@ -234,11 +275,11 @@ namespace {
LL_FORCE_INLINE void writeANSI(const std::string& ansi_code, const std::string& message) LL_FORCE_INLINE void writeANSI(const std::string& ansi_code, const std::string& message)
{ {
LL_PROFILE_ZONE_SCOPED LL_PROFILE_ZONE_SCOPED
static std::string s_ansi_bold = createANSI("1"); // bold static std::string s_ansi_bold = createBoldANSI(); // bold text
static std::string s_ansi_reset = createANSI("0"); // reset static std::string s_ansi_reset = createResetANSI(); // reset
// ANSI color code escape sequence, message, and reset in one fprintf call // ANSI color code escape sequence, message, and reset in one fprintf call
// Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries. // Default all message levels to bold so we can distinguish our own messages from those dumped by subprocesses and libraries.
fprintf(stderr, "%s%s%s\n%s", s_ansi_bold.c_str(), ansi_code.c_str(), message.c_str(), s_ansi_reset.c_str() ); fprintf(stderr, "%s%s\n%s", ansi_code.c_str(), message.c_str(), s_ansi_reset.c_str() );
} }
static bool checkANSI(void) static bool checkANSI(void)

View File

@ -27,7 +27,6 @@
#ifndef LL_LLTHREAD_H #ifndef LL_LLTHREAD_H
#define LL_LLTHREAD_H #define LL_LLTHREAD_H
#include "llapp.h"
#include "llapr.h" #include "llapr.h"
#include "boost/intrusive_ptr.hpp" #include "boost/intrusive_ptr.hpp"
#include "llrefcount.h" #include "llrefcount.h"

View File

@ -33,6 +33,7 @@
#include <iphlpapi.h> #include <iphlpapi.h>
#endif #endif
#include "llapp.h"
#include "lldefs.h" #include "lldefs.h"
#include "llerror.h" #include "llerror.h"

View File

@ -7,7 +7,7 @@ include(LLCoreHttp)
include(LLCommon) include(LLCommon)
include(LLMath) include(LLMath)
include(LLMessage) include(LLMessage)
include(LLVFS) include(LLFileSystem)
include(LLXML) include(LLXML)
include_directories( include_directories(
@ -15,7 +15,7 @@ include_directories(
${LLCOMMON_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS}
) )
include_directories(SYSTEM include_directories(SYSTEM

View File

@ -1,5 +1,5 @@
/** /**
* @file llpidlock.h * @file llcrashlock.h
* @brief Maintainence of disk locking files for crash reporting * @brief Maintainence of disk locking files for crash reporting
* *
* $LicenseInfo:firstyear=2001&license=viewerlgpl$ * $LicenseInfo:firstyear=2001&license=viewerlgpl$

View File

@ -596,7 +596,7 @@ bool LLCrashLogger::init()
#if LL_WINDOWS #if LL_WINDOWS
Sleep(1000); Sleep(1000);
#else #else
sleep(1); ::sleep(1);
#endif #endif
locked = mKeyMaster.checkMaster(); locked = mKeyMaster.checkMaster();
} }

View File

@ -1,6 +1,6 @@
# -*- cmake -*- # -*- cmake -*-
project(llvfs) project(llfilesystem)
include(00-Common) include(00-Common)
include(LLCommon) include(LLCommon)
@ -11,39 +11,34 @@ include_directories(
${LLCOMMON_SYSTEM_INCLUDE_DIRS} ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
) )
set(llvfs_SOURCE_FILES set(llfilesystem_SOURCE_FILES
lldir.cpp lldir.cpp
lldiriterator.cpp lldiriterator.cpp
lllfsthread.cpp lllfsthread.cpp
llpidlock.cpp lldiskcache.cpp
llvfile.cpp llfilesystem.cpp
llvfs.cpp
llvfsthread.cpp
) )
set(llvfs_HEADER_FILES set(llfilesystem_HEADER_FILES
CMakeLists.txt CMakeLists.txt
lldir.h lldir.h
lldirguard.h lldirguard.h
lldiriterator.h lldiriterator.h
lllfsthread.h lllfsthread.h
llpidlock.h lldiskcache.h
llvfile.h llfilesystem.h
llvfs.h
llvfsthread.h
) )
if (DARWIN) if (DARWIN)
LIST(APPEND llvfs_SOURCE_FILES lldir_mac.cpp) LIST(APPEND llfilesystem_SOURCE_FILES lldir_utils_objc.mm)
LIST(APPEND llvfs_HEADER_FILES lldir_mac.h) LIST(APPEND llfilesystem_SOURCE_FILES lldir_utils_objc.h)
LIST(APPEND llvfs_SOURCE_FILES llvfs_objc.mm) LIST(APPEND llfilesystem_SOURCE_FILES lldir_mac.cpp)
LIST(APPEND llvfs_HEADER_FILES llvfs_objc.h) LIST(APPEND llfilesystem_HEADER_FILES lldir_mac.h)
endif (DARWIN) endif (DARWIN)
if (LINUX) if (LINUX)
LIST(APPEND llvfs_SOURCE_FILES lldir_linux.cpp) LIST(APPEND llfilesystem_SOURCE_FILES lldir_linux.cpp)
LIST(APPEND llvfs_HEADER_FILES lldir_linux.h) LIST(APPEND llfilesystem_HEADER_FILES lldir_linux.h)
if (INSTALL) if (INSTALL)
set_source_files_properties(lldir_linux.cpp set_source_files_properties(lldir_linux.cpp
@ -54,31 +49,31 @@ if (LINUX)
endif (LINUX) endif (LINUX)
if (WINDOWS) if (WINDOWS)
LIST(APPEND llvfs_SOURCE_FILES lldir_win32.cpp) LIST(APPEND llfilesystem_SOURCE_FILES lldir_win32.cpp)
LIST(APPEND llvfs_HEADER_FILES lldir_win32.h) LIST(APPEND llfilesystem_HEADER_FILES lldir_win32.h)
endif (WINDOWS) endif (WINDOWS)
set_source_files_properties(${llvfs_HEADER_FILES} set_source_files_properties(${llfilesystem_HEADER_FILES}
PROPERTIES HEADER_FILE_ONLY TRUE) PROPERTIES HEADER_FILE_ONLY TRUE)
list(APPEND llvfs_SOURCE_FILES ${llvfs_HEADER_FILES}) list(APPEND llfilesystem_SOURCE_FILES ${llfilesystem_HEADER_FILES})
add_library (llvfs ${llvfs_SOURCE_FILES}) add_library (llfilesystem ${llfilesystem_SOURCE_FILES})
set(vfs_BOOST_LIBRARIES set(cache_BOOST_LIBRARIES
${BOOST_FILESYSTEM_LIBRARY} ${BOOST_FILESYSTEM_LIBRARY}
${BOOST_SYSTEM_LIBRARY} ${BOOST_SYSTEM_LIBRARY}
) )
target_link_libraries(llvfs target_link_libraries(llfilesystem
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${vfs_BOOST_LIBRARIES} ${cache_BOOST_LIBRARIES}
) )
if (DARWIN) if (DARWIN)
include(CMakeFindFrameworks) include(CMakeFindFrameworks)
find_library(COCOA_LIBRARY Cocoa) find_library(COCOA_LIBRARY Cocoa)
target_link_libraries(llvfs ${COCOA_LIBRARY}) target_link_libraries(llfilesystem ${COCOA_LIBRARY})
endif (DARWIN) endif (DARWIN)
@ -86,18 +81,18 @@ endif (DARWIN)
if (LL_TESTS) if (LL_TESTS)
include(LLAddBuildTest) include(LLAddBuildTest)
# UNIT TESTS # UNIT TESTS
SET(llvfs_TEST_SOURCE_FILES SET(llfilesystem_TEST_SOURCE_FILES
lldiriterator.cpp lldiriterator.cpp
) )
set_source_files_properties(lldiriterator.cpp set_source_files_properties(lldiriterator.cpp
PROPERTIES PROPERTIES
LL_TEST_ADDITIONAL_LIBRARIES "${vfs_BOOST_LIBRARIES}" LL_TEST_ADDITIONAL_LIBRARIES "${cache_BOOST_LIBRARIES}"
) )
LL_ADD_PROJECT_UNIT_TESTS(llvfs "${llvfs_TEST_SOURCE_FILES}") LL_ADD_PROJECT_UNIT_TESTS(llfilesystem "${llfilesystem_TEST_SOURCE_FILES}")
# INTEGRATION TESTS # INTEGRATION TESTS
set(test_libs llmath llcommon llvfs ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) set(test_libs llmath llcommon llfilesystem ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
# TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests. # TODO: Some of these need refactoring to be proper Unit tests rather than Integration tests.
LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lldir "" "${test_libs}")

View File

@ -36,7 +36,7 @@
#include <unistd.h> #include <unistd.h>
#include <glob.h> #include <glob.h>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include "llvfs_objc.h" #include "lldir_utils_objc.h"
// -------------------------------------------------------------------------------- // --------------------------------------------------------------------------------

View File

@ -1,10 +1,10 @@
/** /**
* @file llvfs_objc.h * @file lldir_utils_objc.h
* @brief Definition of directory utilities class for Mac OS X * @brief Definition of directory utilities class for Mac OS X
* *
* $LicenseInfo:firstyear=2000&license=viewerlgpl$ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc. * Copyright (C) 2020, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -28,8 +28,8 @@
#error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead. #error This header must not be included when compiling for any target other than Mac OS. Consider including lldir.h instead.
#endif // !LL_DARWIN #endif // !LL_DARWIN
#ifndef LL_LLVFS_OBJC_H #ifndef LL_LLDIR_UTILS_OBJC_H
#define LL_LLVFS_OBJC_H #define LL_LLDIR_UTILS_OBJC_H
#include <iostream> #include <iostream>
@ -40,4 +40,4 @@ std::string* getSystemResourceFolder();
std::string* getSystemExecutableFolder(); std::string* getSystemExecutableFolder();
#endif // LL_LLVFS_OBJC_H #endif // LL_LLDIR_UTILS_OBJC_H

View File

@ -1,10 +1,10 @@
/** /**
* @file llvfs_objc.cpp * @file lldir_utils_objc.mm
* @brief Cocoa implementation of directory utilities for Mac OS X * @brief Cocoa implementation of directory utilities for Mac OS X
* *
* $LicenseInfo:firstyear=2002&license=viewerlgpl$ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc. * Copyright (C) 2020, Linden Research, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -27,7 +27,7 @@
//WARNING: This file CANNOT use standard linden includes due to conflicts between definitions of BOOL //WARNING: This file CANNOT use standard linden includes due to conflicts between definitions of BOOL
#include "llvfs_objc.h" #include "lldir_utils_objc.h"
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
std::string* getSystemTempFolder() std::string* getSystemTempFolder()

View File

@ -0,0 +1,410 @@
/**
* @file lldiskcache.cpp
* @brief The disk cache implementation.
*
* Note: Rather than keep the top level function comments up
* to date in both the source and header files, I elected to
* only have explicit comments about each function and variable
* in the header - look there for details. The same is true for
* description of how this code is supposed to work.
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2020, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llapp.h"
#include "llassettype.h"
#include "lldir.h"
#include <boost/filesystem.hpp>
#include <boost/range/iterator_range.hpp>
#include <chrono>
#include "lldiskcache.h"
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";
LLFile::mkdir(cache_dir);
}
// WARNING: purge() is called by LLPurgeDiskCacheThread. As such it must
// NOT touch any LLDiskCache data without introducing and locking a mutex!
// Interaction through the filesystem itself should be safe. Lets say thread
// A is accessing the cache file for reading/writing and thread B is trimming
// the cache. Lets also assume using llifstream to open a file and
// boost::filesystem::remove are not atomic (which will be pretty much the
// case).
// Now, A is trying to open the file using llifstream ctor. It does some
// checks if the file exists and whatever else it might be doing, but has not
// issued the call to the OS to actually open the file yet. Now B tries to
// delete the file: If the file has been already marked as in use by the OS,
// deleting the file will fail and B will continue with the next file. A can
// safely continue opening the file. If the file has not yet been marked as in
// use, B will delete the file. Now A actually wants to open it, operation
// will fail, subsequent check via llifstream.is_open will fail, asset will
// have to be re-requested. (Assuming here the viewer will actually handle
// this situation properly, that can also happen if there is a file containing
// garbage.)
// Other situation: B is trimming the cache and A wants to read a file that is
// about to get deleted. boost::filesystem::remove does whatever it is doing
// before actually deleting the file. If A opens the file before the file is
// actually gone, the OS call from B to delete the file will fail since the OS
// will prevent this. B continues with the next file. If the file is already
// gone before A finally gets to open it, this operation will fail and the
// asset will have to be re-requested.
void LLDiskCache::purge()
{
if (mEnableCacheDebugInfo)
{
LL_INFOS() << "Total dir size before purge is " << dirFileSize(mCacheDir) << LL_ENDL;
}
boost::system::error_code ec;
auto start_time = std::chrono::high_resolution_clock::now();
typedef std::pair<std::time_t, std::pair<uintmax_t, std::string>> file_info_t;
std::vector<file_info_t> file_info;
#if LL_WINDOWS
std::wstring cache_path(utf8str_to_utf16str(mCacheDir));
#else
std::string cache_path(mCacheDir);
#endif
if (boost::filesystem::is_directory(cache_path, ec) && !ec.failed())
{
for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(cache_path, ec), {}))
{
if (boost::filesystem::is_regular_file(entry, ec) && !ec.failed())
{
if (entry.path().string().find(mCacheFilenamePrefix) != std::string::npos)
{
uintmax_t file_size = boost::filesystem::file_size(entry, ec);
if (ec.failed())
{
continue;
}
const std::string file_path = entry.path().string();
const std::time_t file_time = boost::filesystem::last_write_time(entry, ec);
if (ec.failed())
{
continue;
}
file_info.push_back(file_info_t(file_time, { file_size, file_path }));
}
}
}
}
std::sort(file_info.begin(), file_info.end(), [](file_info_t& x, file_info_t& y)
{
return x.first > y.first;
});
LL_INFOS() << "Purging cache to a maximum of " << mMaxSizeBytes << " bytes" << LL_ENDL;
uintmax_t file_size_total = 0;
for (file_info_t& entry : file_info)
{
file_size_total += entry.second.first;
std::string action = "";
if (file_size_total > mMaxSizeBytes)
{
action = "DELETE:";
boost::filesystem::remove(entry.second.second, ec);
if (ec.failed())
{
LL_WARNS() << "Failed to delete cache file " << entry.second.second << ": " << ec.message() << LL_ENDL;
}
}
else
{
action = " KEEP:";
}
if (mEnableCacheDebugInfo)
{
// have to do this because of LL_INFO/LL_END weirdness
std::ostringstream line;
line << action << " ";
line << entry.first << " ";
line << entry.second.first << " ";
line << entry.second.second;
line << " (" << file_size_total << "/" << mMaxSizeBytes << ")";
LL_INFOS() << line.str() << LL_ENDL;
}
}
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();
LL_INFOS() << "Total dir size after purge is " << dirFileSize(mCacheDir) << 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_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); // 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;
}
}
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;
cache_info << std::fixed;
cache_info << std::setprecision(1);
cache_info << "Max size " << max_in_mb << " MB ";
cache_info << "(" << percent_used << "% used)";
return cache_info.str();
}
void LLDiskCache::clearCache()
{
/**
* See notes on performance in dirFileSize(..) - there may be
* a quicker way to do this by operating on the parent dir vs
* the component files but it's called infrequently so it's
* likely just fine
*/
boost::system::error_code ec;
#if LL_WINDOWS
std::wstring cache_path(utf8str_to_utf16str(mCacheDir));
#else
std::string cache_path(mCacheDir);
#endif
if (boost::filesystem::is_directory(cache_path, ec) && !ec.failed())
{
for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(cache_path, ec), {}))
{
if (boost::filesystem::is_regular_file(entry, ec) && !ec.failed())
{
if (entry.path().string().find(mCacheFilenamePrefix) != std::string::npos)
{
boost::filesystem::remove(entry, ec);
if (ec.failed())
{
LL_WARNS() << "Failed to delete cache file " << entry << ": " << ec.message() << LL_ENDL;
}
}
}
}
}
}
uintmax_t LLDiskCache::dirFileSize(const std::string dir)
{
uintmax_t total_file_size = 0;
/**
* There may be a better way that works directly on the folder (similar to
* right clicking on a folder in the OS and asking for size vs right clicking
* on all files and adding up manually) but this is very fast - less than 100ms
* for 10,000 files in my testing so, so long as it's not called frequently,
* it should be okay. Note that's it's only currently used for logging/debugging
* so if performance is ever an issue, optimizing this or removing it altogether,
* is an easy win.
*/
boost::system::error_code ec;
#if LL_WINDOWS
std::wstring dir_path(utf8str_to_utf16str(dir));
#else
std::string dir_path(dir);
#endif
if (boost::filesystem::is_directory(dir_path, ec) && !ec.failed())
{
for (auto& entry : boost::make_iterator_range(boost::filesystem::directory_iterator(dir_path, ec), {}))
{
if (boost::filesystem::is_regular_file(entry, ec) && !ec.failed())
{
if (entry.path().string().find(mCacheFilenamePrefix) != std::string::npos)
{
uintmax_t file_size = boost::filesystem::file_size(entry, ec);
if (!ec.failed())
{
total_file_size += file_size;
}
}
}
}
}
return total_file_size;
}
LLPurgeDiskCacheThread::LLPurgeDiskCacheThread() :
LLThread("PurgeDiskCacheThread", nullptr)
{
}
void LLPurgeDiskCacheThread::run()
{
constexpr std::chrono::seconds CHECK_INTERVAL{60};
while (LLApp::instance()->sleep(CHECK_INTERVAL))
{
LLDiskCache::instance().purge();
}
}

View File

@ -0,0 +1,198 @@
/**
* @file lldiskcache.h
* @brief The disk cache implementation declarations.
*
* @Description:
* This code implements a disk cache using the following ideas:
* 1/ The metadata for a file can be encapsulated in the filename.
The filenames will be composed of the following fields:
Prefix: Used to identify the file as a part of the cache.
An additional reason for using a prefix is that it
might be possible, either accidentally or maliciously
to end up with the cache dir set to a non-cache
location such as your OS system dir or a work folder.
Purging files from that would obviously be a disaster
so this is an extra step to help avoid that scenario.
ID: Typically the asset ID (UUID) of the asset being
saved but can be anything valid for a filename
Extra Info: A field for use in the future that can be used
to store extra identifiers - e.g. the discard
level of a JPEG2000 file
Asset Type: A text string created from the LLAssetType enum
that identifies the type of asset being stored.
.asset A file extension of .asset is used to help
identify this as a Viewer asset file
* 2/ The time of last access for a file can be updated instantly
* for file reads and automatically as part of the file writes.
* 3/ The purge algorithm collects a list of all files in the
* directory, sorts them by date of last access (write) and then
* deletes any files based on age until the total size of all
* the files is less than the maximum size specified.
* 4/ An LLSingleton idiom is used since there will only ever be
* a single cache and we want to access it from numerous places.
* 5/ Performance on my modest system seems very acceptable. For
* example, in testing, I was able to purge a directory of
* 10,000 files, deleting about half of them in ~ 1700ms. For
* the same sized directory of files, writing the last updated
* time to each took less than 600ms indicating that this
* important part of the mechanism has almost no overhead.
*
* $LicenseInfo:firstyear=2009&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2020, 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$
*/
#ifndef _LLDISKCACHE
#define _LLDISKCACHE
#include "llsingleton.h"
class LLDiskCache :
public LLParamSingleton<LLDiskCache>
{
public:
/**
* Since this is using the LLSingleton pattern but we
* want to allow the constructor to be called first
* with various parameters, we also invoke the
* LLParamSingleton idiom and use it to initialize
* the class via a call in LLAppViewer.
*/
LLSINGLETON(LLDiskCache,
/**
* The full name of the cache folder - typically a
* a child of the main Viewer cache directory. Defined
* by the setting at 'DiskCacheDirName'
*/
const std::string cache_dir,
/**
* The maximum size of the cache in bytes - Based on the
* setting at 'CacheSize' and 'DiskCachePercentOfTotal'
*/
const uintmax_t max_size_bytes,
/**
* A flag that enables extra cache debugging so that
* if there are bugs, we can ask uses to enable this
* setting and send us their logs
*/
const bool enable_cache_debug_info);
virtual ~LLDiskCache() = default;
public:
/**
* 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 is up to date (This is used in the mechanism for purging the cache)
*/
void updateFileAccessTime(const std::string file_path);
/**
* Purge the oldest items in the cache so that the combined size of all files
* is no bigger than mMaxSizeBytes.
*
* WARNING: purge() is called by LLPurgeDiskCacheThread. As such it must
* NOT touch any LLDiskCache data without introducing and locking a mutex!
*
* Purging the disk cache involves nontrivial work on the viewer's
* filesystem. If called on the main thread, this causes a noticeable
* freeze.
*/
void purge();
/**
* Clear the cache by removing all the files in the specified cache
* directory individually. Only the files that contain a prefix defined
* by mCacheFilenamePrefix will be removed.
*/
void clearCache();
/**
* Return some information about the cache for use in About Box etc.
*/
const std::string getCacheInfo();
private:
/**
* Utility function to gather the total size the files in a given
* 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:
/**
* 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
*/
uintmax_t mMaxSizeBytes;
/**
* The folder that holds the cached files. The consumer of this
* class must avoid letting the user set this location as a malicious
* 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;
/**
* When enabled, displays additional debugging information in
* various parts of the code
*/
bool mEnableCacheDebugInfo;
};
class LLPurgeDiskCacheThread : public LLThread
{
public:
LLPurgeDiskCacheThread();
protected:
void run() override;
};
#endif // _LLDISKCACHE

View File

@ -0,0 +1,326 @@
/**
* @file filesystem.h
* @brief Simulate local file system operations.
* @Note The initial implementation does actually use standard C++
* file operations but eventually, there will be another
* layer that caches and manages file meta data too.
*
* $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$
*/
#include "linden_common.h"
#include "lldir.h"
#include "llfilesystem.h"
#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
static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait");
LLFileSystem::LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_type, S32 mode)
{
mFileType = file_type;
mFileID = file_id;
mPosition = 0;
mBytesRead = 0;
mMode = mode;
// This block of code was originally called in the read() method but after comments here:
// https://bitbucket.org/lindenlab/viewer/commits/e28c1b46e9944f0215a13cab8ee7dded88d7fc90#comment-10537114
// we decided to follow Henri's suggestion and move the code to update the last access time here.
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);
// 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
// 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
bool exists = gDirUtilp->fileExists(filename);
if (exists)
{
LLDiskCache::getInstance()->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);
llifstream 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, 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);
LLFile::remove(filename.c_str(), suppress_error);
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)
{
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);
// Rename needs the new file to not exist.
LLFileSystem::removeFile(new_file_id, new_file_type, ENOENT);
if (LLFile::rename(old_filename, new_filename) != 0)
{
// 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...
//return FALSE;
LL_WARNS() << "Failed to rename " << old_file_id << " to " << new_id_str << " reason: " << strerror(errno) << LL_ENDL;
}
return TRUE;
}
// 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);
S32 file_size = 0;
llifstream file(filename, std::ios::binary);
if (file.is_open())
{
file.seekg(0, std::ios::end);
file_size = file.tellg();
}
return file_size;
}
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);
llifstream file(filename, std::ios::binary);
if (file.is_open())
{
file.seekg(mPosition, std::ios::beg);
file.read((char*)buffer, bytes);
if (file)
{
mBytesRead = bytes;
}
else
{
mBytesRead = file.gcount();
}
file.close();
mPosition += mBytesRead;
if (mBytesRead)
{
success = TRUE;
}
}
return success;
}
S32 LLFileSystem::getLastBytesRead()
{
return mBytesRead;
}
BOOL LLFileSystem::eof()
{
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);
BOOL success = FALSE;
if (mMode == APPEND)
{
llofstream ofs(filename, std::ios::app | std::ios::binary);
if (ofs)
{
ofs.write((const char*)buffer, bytes);
mPosition = ofs.tellp(); // <FS:Ansariel> Fix asset caching
success = TRUE;
}
}
// <FS:Ansariel> Fix asset caching
else if (mMode == READ_WRITE)
{
// Don't truncate if file already exists
llofstream ofs(filename, std::ios::in | std::ios::binary);
if (ofs)
{
ofs.seekp(mPosition, std::ios::beg);
ofs.write((const char*)buffer, bytes);
mPosition += bytes;
success = TRUE;
}
else
{
// File doesn't exist - open in write mode
ofs.open(filename, std::ios::binary);
if (ofs.is_open())
{
ofs.write((const char*)buffer, bytes);
mPosition += bytes;
success = TRUE;
}
}
}
// </FS:Ansariel>
else
{
llofstream ofs(filename, std::ios::binary);
if (ofs)
{
ofs.write((const char*)buffer, bytes);
mPosition += bytes;
success = TRUE;
}
}
return success;
}
BOOL LLFileSystem::seek(S32 offset, S32 origin)
{
if (-1 == origin)
{
origin = mPosition;
}
S32 new_pos = origin + offset;
S32 size = getSize();
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 = 0;
return FALSE;
}
mPosition = new_pos;
return TRUE;
}
S32 LLFileSystem::tell() const
{
return mPosition;
}
S32 LLFileSystem::getSize()
{
return LLFileSystem::getFileSize(mFileID, mFileType);
}
S32 LLFileSystem::getMaxSize()
{
// 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)
{
LLFileSystem::renameFile(mFileID, mFileType, new_id, new_type);
mFileID = new_id;
mFileType = new_type;
return TRUE;
}
BOOL LLFileSystem::remove()
{
LLFileSystem::removeFile(mFileID, mFileType);
return TRUE;
}

View File

@ -0,0 +1,78 @@
/**
* @file filesystem.h
* @brief Simulate local file system operations.
* @Note The initial implementation does actually use standard C++
* file operations but eventually, there will be another
* layer that caches and manages file meta data too.
*
* $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$
*/
#ifndef LL_FILESYSTEM_H
#define LL_FILESYSTEM_H
#include "lluuid.h"
#include "llassettype.h"
#include "lldiskcache.h"
class LLFileSystem
{
public:
LLFileSystem(const LLUUID& file_id, const LLAssetType::EType file_type, S32 mode = LLFileSystem::READ);
~LLFileSystem();
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;
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, int suppress_error = 0);
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;
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

View File

@ -6,7 +6,7 @@ include(00-Common)
include(LLCommon) include(LLCommon)
include(LLImage) include(LLImage)
include(LLMath) include(LLMath)
include(LLVFS) include(LLFileSystem)
include(LLKDU) include(LLKDU)
include(LLImageJ2COJ) include(LLImageJ2COJ)
include(ZLIB) include(ZLIB)
@ -18,7 +18,7 @@ include_directories(
${LLCOMMON_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS}
${LLCOMMON_SYSTEM_INCLUDE_DIRS} ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${PNG_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS}
) )
@ -69,7 +69,7 @@ else (USE_KDU)
endif (USE_KDU) endif (USE_KDU)
target_link_libraries(llimage target_link_libraries(llimage
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${JPEG_LIBRARIES} ${JPEG_LIBRARIES}

View File

@ -2219,20 +2219,11 @@ bool LLImageFormatted::save(const std::string &filename)
return true; return true;
} }
// bool LLImageFormatted::save(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
// Depricated to remove VFS dependency.
// Use:
// LLVFile::writeFile(image->getData(), image->getDataSize(), vfs, uuid, type);
//----------------------------------------------------------------------------
S8 LLImageFormatted::getCodec() const S8 LLImageFormatted::getCodec() const
{ {
return mCodec; return mCodec;
} }
//============================================================================
static void avg4_colors4(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst) static void avg4_colors4(const U8* a, const U8* b, const U8* c, const U8* d, U8* dst)
{ {
dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2); dst[0] = (U8)(((U32)(a[0]) + b[0] + c[0] + d[0])>>2);

View File

@ -7,7 +7,7 @@ include(LLCommon)
include(LLCoreHttp) include(LLCoreHttp)
include(LLMath) include(LLMath)
include(LLMessage) include(LLMessage)
include(LLVFS) include(LLFileSystem)
include(LLXML) include(LLXML)
include_directories( include_directories(
@ -81,7 +81,7 @@ if (LL_TESTS)
LL_ADD_PROJECT_UNIT_TESTS(llinventory "${llinventory_TEST_SOURCE_FILES}") LL_ADD_PROJECT_UNIT_TESTS(llinventory "${llinventory_TEST_SOURCE_FILES}")
#set(TEST_DEBUG on) #set(TEST_DEBUG on)
set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLVFS_LIBRARIES} ${LLCOREHTTP_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES}) set(test_libs llinventory ${LLMESSAGE_LIBRARIES} ${LLFILESYSTEM_LIBRARIES} ${LLCOREHTTP_LIBRARIES} ${LLMATH_LIBRARIES} ${LLCOMMON_LIBRARIES} ${WINDOWS_LIBRARIES})
LL_ADD_INTEGRATION_TEST(inventorymisc "" "${test_libs}") LL_ADD_INTEGRATION_TEST(inventorymisc "" "${test_libs}")
LL_ADD_INTEGRATION_TEST(llparcel "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llparcel "" "${test_libs}")
endif (LL_TESTS) endif (LL_TESTS)

View File

@ -9,7 +9,7 @@ include(LLCommon)
include(LLCoreHttp) include(LLCoreHttp)
include(LLMath) include(LLMath)
include(LLMessage) include(LLMessage)
include(LLVFS) include(LLFileSystem)
include(LLAddBuildTest) include(LLAddBuildTest)
include(Python) include(Python)
include(Tut) include(Tut)
@ -23,7 +23,7 @@ include_directories(
${LLCOREHTTP_INCLUDE_DIRS} ${LLCOREHTTP_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLMESSAGE_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${JSONCPP_INCLUDE_DIR} ${JSONCPP_INCLUDE_DIR}
) )
@ -209,7 +209,7 @@ target_link_libraries(
llmessage llmessage
${CURL_LIBRARIES} ${CURL_LIBRARIES}
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${JSONCPP_LIBRARIES} ${JSONCPP_LIBRARIES}
${OPENSSL_LIBRARIES} ${OPENSSL_LIBRARIES}
@ -227,7 +227,7 @@ target_link_libraries(
llmessage llmessage
${CURL_LIBRARIES} ${CURL_LIBRARIES}
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${JSONCPP_LIBRARIES} ${JSONCPP_LIBRARIES}
${OPENSSL_LIBRARIES} ${OPENSSL_LIBRARIES}
@ -257,7 +257,7 @@ if (LL_TESTS)
if (LINUX) if (LINUX)
set(test_libs set(test_libs
${WINDOWS_LIBRARIES} ${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${CURL_LIBRARIES} ${CURL_LIBRARIES}
${NGHTTP2_LIBRARIES} ${NGHTTP2_LIBRARIES}
@ -273,7 +273,7 @@ if (LINUX)
else (LINUX) else (LINUX)
set(test_libs set(test_libs
${WINDOWS_LIBRARIES} ${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${CURL_LIBRARIES} ${CURL_LIBRARIES}
${NGHTTP2_LIBRARIES} ${NGHTTP2_LIBRARIES}

View File

@ -42,8 +42,7 @@
// this library includes // this library includes
#include "message.h" #include "message.h"
#include "llxfermanager.h" #include "llxfermanager.h"
#include "llvfile.h" #include "llfilesystem.h"
#include "llvfs.h"
#include "lldbstrings.h" #include "lldbstrings.h"
#include "lltransfersourceasset.h" #include "lltransfersourceasset.h"
@ -202,7 +201,7 @@ LLBaseDownloadRequest::LLBaseDownloadRequest(const LLUUID &uuid, const LLAssetTy
mIsTemp(FALSE), mIsTemp(FALSE),
mIsPriority(FALSE), mIsPriority(FALSE),
mDataSentInFirstPacket(FALSE), mDataSentInFirstPacket(FALSE),
mDataIsInVFS(FALSE) mDataIsInCache(FALSE)
{ {
// Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been // Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
// running a message system loop. // running a message system loop.
@ -266,7 +265,8 @@ LLSD LLAssetRequest::getFullDetails() const
sd["is_local"] = mIsLocal; sd["is_local"] = mIsLocal;
sd["is_priority"] = mIsPriority; sd["is_priority"] = mIsPriority;
sd["data_send_in_first_packet"] = mDataSentInFirstPacket; sd["data_send_in_first_packet"] = mDataSentInFirstPacket;
sd["data_is_in_vfs"] = mDataIsInVFS; // Note: cannot change this (easily) since it is consumed by server
sd["data_is_in_vfs"] = mDataIsInCache;
return sd; return sd;
} }
@ -330,28 +330,23 @@ LLBaseDownloadRequest* LLEstateAssetRequest::getCopy()
// TODO: rework tempfile handling? // TODO: rework tempfile handling?
LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLVFS *vfs, LLVFS *static_vfs, const LLHost &upstream_host) LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, const LLHost &upstream_host)
{ {
_init(msg, xfer, vfs, static_vfs, upstream_host); _init(msg, xfer, upstream_host);
} }
LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLAssetStorage::LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer)
LLVFS *vfs, LLVFS *static_vfs)
{ {
_init(msg, xfer, vfs, static_vfs, LLHost()); _init(msg, xfer, LLHost());
} }
void LLAssetStorage::_init(LLMessageSystem *msg, void LLAssetStorage::_init(LLMessageSystem *msg,
LLXferManager *xfer, LLXferManager *xfer,
LLVFS *vfs,
LLVFS *static_vfs,
const LLHost &upstream_host) const LLHost &upstream_host)
{ {
mShutDown = FALSE; mShutDown = FALSE;
mMessageSys = msg; mMessageSys = msg;
mXferManager = xfer; mXferManager = xfer;
mVFS = vfs;
mStaticVFS = static_vfs;
setUpstream(upstream_host); setUpstream(upstream_host);
msg->setHandlerFuncFast(_PREHASH_AssetUploadComplete, processUploadComplete, (void **)this); msg->setHandlerFuncFast(_PREHASH_AssetUploadComplete, processUploadComplete, (void **)this);
@ -430,7 +425,7 @@ void LLAssetStorage::_cleanupRequests(BOOL all, S32 error)
} }
if (tmp->mDownCallback) if (tmp->mDownCallback)
{ {
tmp->mDownCallback(mVFS, tmp->getUUID(), tmp->getType(), tmp->mUserData, error, LLExtStat::NONE); tmp->mDownCallback(tmp->getUUID(), tmp->getType(), tmp->mUserData, error, LLExtStat::NONE);
} }
if (tmp->mInfoCallback) if (tmp->mInfoCallback)
{ {
@ -443,10 +438,10 @@ void LLAssetStorage::_cleanupRequests(BOOL all, S32 error)
BOOL LLAssetStorage::hasLocalAsset(const LLUUID &uuid, const LLAssetType::EType type) BOOL LLAssetStorage::hasLocalAsset(const LLUUID &uuid, const LLAssetType::EType type)
{ {
return mStaticVFS->getExists(uuid, type) || mVFS->getExists(uuid, type); return LLFileSystem::getExists(uuid, type);
} }
bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type, bool LLAssetStorage::findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type,
LLGetAssetCallback callback, void *user_data) LLGetAssetCallback callback, void *user_data)
{ {
if (user_data) if (user_data)
@ -455,17 +450,17 @@ bool LLAssetStorage::findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAsse
llassert(callback != NULL); llassert(callback != NULL);
} }
BOOL exists = mStaticVFS->getExists(uuid, type); BOOL exists = LLFileSystem::getExists(uuid, type);
if (exists) if (exists)
{ {
LLVFile file(mStaticVFS, uuid, type); LLFileSystem file(uuid, type);
U32 size = file.getSize(); U32 size = file.getSize();
if (size > 0) if (size > 0)
{ {
// we've already got the file // we've already got the file
if (callback) if (callback)
{ {
callback(mStaticVFS, uuid, type, user_data, LL_ERR_NOERR, LLExtStat::VFS_CACHED); callback(uuid, type, user_data, LL_ERR_NOERR, LLExtStat::CACHE_CACHED);
} }
return true; return true;
} }
@ -506,7 +501,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
if (callback) if (callback)
{ {
add(sFailedDownloadCount, 1); add(sFailedDownloadCount, 1);
callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_FAILED, LLExtStat::NONE); callback(uuid, type, user_data, LL_ERR_ASSET_REQUEST_FAILED, LLExtStat::NONE);
} }
return; return;
} }
@ -517,20 +512,19 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
if (callback) if (callback)
{ {
add(sFailedDownloadCount, 1); add(sFailedDownloadCount, 1);
callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LLExtStat::NULL_UUID); callback(uuid, type, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LLExtStat::NULL_UUID);
} }
return; return;
} }
// Try static VFS first. if (findInCacheAndInvokeCallback(uuid,type,callback,user_data))
if (findInStaticVFSAndInvokeCallback(uuid,type,callback,user_data))
{ {
LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << uuid << " found in static VFS" << LL_ENDL; LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << uuid << " found in cache" << LL_ENDL;
return; return;
} }
BOOL exists = mVFS->getExists(uuid, type); BOOL exists = LLFileSystem::getExists(uuid, type);
LLVFile file(mVFS, uuid, type); LLFileSystem file(uuid, type);
U32 size = exists ? file.getSize() : 0; U32 size = exists ? file.getSize() : 0;
if (size > 0) if (size > 0)
@ -540,10 +534,10 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
// unless there's a weird error // unless there's a weird error
if (callback) if (callback)
{ {
callback(mVFS, uuid, type, user_data, LL_ERR_NOERR, LLExtStat::VFS_CACHED); callback(uuid, type, user_data, LL_ERR_NOERR, LLExtStat::CACHE_CACHED);
} }
LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << uuid << " found in VFS" << LL_ENDL; LL_DEBUGS("AssetStorage") << "ASSET_TRACE asset " << uuid << " found in cache" << LL_ENDL;
} }
else else
{ {
@ -616,7 +610,7 @@ void LLAssetStorage::removeAndCallbackPendingDownloads(const LLUUID& file_id, LL
{ {
add(sFailedDownloadCount, 1); add(sFailedDownloadCount, 1);
} }
tmp->mDownCallback(gAssetStorage->mVFS, callback_id, callback_type, tmp->mUserData, result_code, ext_status); tmp->mDownCallback(callback_id, callback_type, tmp->mUserData, result_code, ext_status);
} }
delete tmp; delete tmp;
} }
@ -670,7 +664,7 @@ void LLAssetStorage::downloadCompleteCallback(
if (LL_ERR_NOERR == result) if (LL_ERR_NOERR == result)
{ {
// we might have gotten a zero-size file // we might have gotten a zero-size file
LLVFile vfile(gAssetStorage->mVFS, callback_id, callback_type); LLFileSystem vfile(callback_id, callback_type);
if (vfile.getSize() <= 0) if (vfile.getSize() <= 0)
{ {
LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset " << callback_id << LL_ENDL; LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset " << callback_id << LL_ENDL;
@ -719,19 +713,19 @@ void LLAssetStorage::getEstateAsset(
if (callback) if (callback)
{ {
add(sFailedDownloadCount, 1); add(sFailedDownloadCount, 1);
callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LLExtStat::NULL_UUID); callback(asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LLExtStat::NULL_UUID);
} }
return; return;
} }
// Try static VFS first. // Try static first.
if (findInStaticVFSAndInvokeCallback(asset_id,atype,callback,user_data)) if (findInCacheAndInvokeCallback(asset_id,atype,callback,user_data))
{ {
return; return;
} }
BOOL exists = mVFS->getExists(asset_id, atype); BOOL exists = LLFileSystem::getExists(asset_id, atype);
LLVFile file(mVFS, asset_id, atype); LLFileSystem file(asset_id, atype);
U32 size = exists ? file.getSize() : 0; U32 size = exists ? file.getSize() : 0;
if (size > 0) if (size > 0)
@ -741,7 +735,7 @@ void LLAssetStorage::getEstateAsset(
// unless there's a weird error // unless there's a weird error
if (callback) if (callback)
{ {
callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LLExtStat::VFS_CACHED); callback(asset_id, atype, user_data, LL_ERR_NOERR, LLExtStat::CACHE_CACHED);
} }
} }
else else
@ -792,7 +786,7 @@ void LLAssetStorage::getEstateAsset(
if (callback) if (callback)
{ {
add(sFailedDownloadCount, 1); add(sFailedDownloadCount, 1);
callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LLExtStat::NO_UPSTREAM); callback(asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LLExtStat::NO_UPSTREAM);
} }
} }
} }
@ -824,7 +818,7 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback(
if (LL_ERR_NOERR == result) if (LL_ERR_NOERR == result)
{ {
// we might have gotten a zero-size file // we might have gotten a zero-size file
LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getAType()); LLFileSystem vfile(req->getUUID(), req->getAType());
if (vfile.getSize() <= 0) if (vfile.getSize() <= 0)
{ {
LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL; LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL;
@ -838,7 +832,7 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback(
{ {
add(sFailedDownloadCount, 1); add(sFailedDownloadCount, 1);
} }
req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getAType(), req->mUserData, result, ext_status); req->mDownCallback(req->getUUID(), req->getAType(), req->mUserData, result, ext_status);
} }
void LLAssetStorage::getInvItemAsset( void LLAssetStorage::getInvItemAsset(
@ -861,14 +855,13 @@ void LLAssetStorage::getInvItemAsset(
if(asset_id.notNull()) if(asset_id.notNull())
{ {
// Try static VFS first. if (findInCacheAndInvokeCallback( asset_id, atype, callback, user_data))
if (findInStaticVFSAndInvokeCallback( asset_id, atype, callback, user_data))
{ {
return; return;
} }
exists = mVFS->getExists(asset_id, atype); exists = LLFileSystem::getExists(asset_id, atype);
LLVFile file(mVFS, asset_id, atype); LLFileSystem file(asset_id, atype);
size = exists ? file.getSize() : 0; size = exists ? file.getSize() : 0;
if(exists && size < 1) if(exists && size < 1)
{ {
@ -885,7 +878,7 @@ void LLAssetStorage::getInvItemAsset(
// unless there's a weird error // unless there's a weird error
if (callback) if (callback)
{ {
callback(mVFS, asset_id, atype, user_data, LL_ERR_NOERR, LLExtStat::VFS_CACHED); callback(asset_id, atype, user_data, LL_ERR_NOERR, LLExtStat::CACHE_CACHED);
} }
} }
else else
@ -936,7 +929,7 @@ void LLAssetStorage::getInvItemAsset(
if (callback) if (callback)
{ {
add(sFailedDownloadCount, 1); add(sFailedDownloadCount, 1);
callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LLExtStat::NO_UPSTREAM); callback(asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LLExtStat::NO_UPSTREAM);
} }
} }
} }
@ -968,7 +961,7 @@ void LLAssetStorage::downloadInvItemCompleteCallback(
if (LL_ERR_NOERR == result) if (LL_ERR_NOERR == result)
{ {
// we might have gotten a zero-size file // we might have gotten a zero-size file
LLVFile vfile(gAssetStorage->mVFS, req->getUUID(), req->getType()); LLFileSystem vfile(req->getUUID(), req->getType());
if (vfile.getSize() <= 0) if (vfile.getSize() <= 0)
{ {
LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL; LL_WARNS("AssetStorage") << "downloadCompleteCallback has non-existent or zero-size asset!" << LL_ENDL;
@ -982,7 +975,7 @@ void LLAssetStorage::downloadInvItemCompleteCallback(
{ {
add(sFailedDownloadCount, 1); add(sFailedDownloadCount, 1);
} }
req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), req->mUserData, result, ext_status); req->mDownCallback(req->getUUID(), req->getType(), req->mUserData, result, ext_status);
} }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@ -1293,7 +1286,7 @@ bool LLAssetStorage::deletePendingRequestImpl(LLAssetStorage::request_list_t* re
if (req->mDownCallback) if (req->mDownCallback)
{ {
add(sFailedDownloadCount, 1); add(sFailedDownloadCount, 1);
req->mDownCallback(mVFS, req->getUUID(), req->getType(), req->mUserData, error, LLExtStat::REQUEST_DROPPED); req->mDownCallback(req->getUUID(), req->getType(), req->mUserData, error, LLExtStat::REQUEST_DROPPED);
} }
if (req->mInfoCallback) if (req->mInfoCallback)
{ {
@ -1363,8 +1356,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
{ {
LLAssetRequest* tmp = *iter++; LLAssetRequest* tmp = *iter++;
//void(*const* cbptr)(LLVFS *, const LLUUID &, LLAssetType::EType, void *, S32, LLExtStat) auto cbptr = tmp->mDownCallback.target<void(*)(const LLUUID &, LLAssetType::EType, void *, S32, LLExtStat)>();
auto cbptr = tmp->mDownCallback.target<void(*)(LLVFS *, const LLUUID &, LLAssetType::EType, void *, S32, LLExtStat)>();
if (type == tmp->getType() && if (type == tmp->getType() &&
uuid == tmp->getUUID() && uuid == tmp->getUUID() &&
@ -1389,8 +1381,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid,
} }
// static // static
void LLAssetStorage::legacyGetDataCallback(LLVFS *vfs, void LLAssetStorage::legacyGetDataCallback(const LLUUID &uuid,
const LLUUID &uuid,
LLAssetType::EType type, LLAssetType::EType type,
void *user_data, void *user_data,
S32 status, S32 status,
@ -1405,7 +1396,7 @@ void LLAssetStorage::legacyGetDataCallback(LLVFS *vfs,
if ( !status if ( !status
&& !toxic ) && !toxic )
{ {
LLVFile file(vfs, uuid, type); LLFileSystem file(uuid, type);
std::string uuid_str; std::string uuid_str;

View File

@ -44,7 +44,6 @@
class LLMessageSystem; class LLMessageSystem;
class LLXferManager; class LLXferManager;
class LLAssetStorage; class LLAssetStorage;
class LLVFS;
class LLSD; class LLSD;
// anything that takes longer than this to download will abort. // anything that takes longer than this to download will abort.
@ -60,11 +59,11 @@ const int LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE = -4;
const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5; const int LL_ERR_INSUFFICIENT_PERMISSIONS = -5;
const int LL_ERR_PRICE_MISMATCH = -23018; const int LL_ERR_PRICE_MISMATCH = -23018;
// *TODO: these typedefs are passed into the VFS via a legacy C function pointer // *TODO: these typedefs are passed into the cache via a legacy C function pointer
// future project would be to convert these to C++ callables (std::function<>) so that // future project would be to convert these to C++ callables (std::function<>) so that
// we can use bind and remove the userData parameter. // we can use bind and remove the userData parameter.
// //
typedef std::function<void(LLVFS *vfs, const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status)> LLGetAssetCallback; typedef std::function<void(const LLUUID &asset_id, LLAssetType::EType asset_type, void *user_data, S32 status, LLExtStat ext_status)> LLGetAssetCallback;
typedef std::function<void(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status)> LLStoreAssetCallback; typedef std::function<void(const LLUUID &asset_id, void *user_data, S32 status, LLExtStat ext_status)> LLStoreAssetCallback;
@ -120,7 +119,6 @@ protected:
public: public:
LLGetAssetCallback mDownCallback; LLGetAssetCallback mDownCallback;
// void(*mDownCallback)(LLVFS*, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat);
void *mUserData; void *mUserData;
LLHost mHost; LLHost mHost;
@ -128,7 +126,7 @@ public:
F64Seconds mTime; // Message system time F64Seconds mTime; // Message system time
BOOL mIsPriority; BOOL mIsPriority;
BOOL mDataSentInFirstPacket; BOOL mDataSentInFirstPacket;
BOOL mDataIsInVFS; BOOL mDataIsInCache;
}; };
class LLAssetRequest : public LLBaseDownloadRequest class LLAssetRequest : public LLBaseDownloadRequest
@ -198,9 +196,6 @@ typedef std::map<LLUUID,U64,lluuid_less> toxic_asset_map_t;
class LLAssetStorage class LLAssetStorage
{ {
public: public:
// VFS member is public because static child methods need it :(
LLVFS *mVFS;
LLVFS *mStaticVFS;
typedef ::LLStoreAssetCallback LLStoreAssetCallback; typedef ::LLStoreAssetCallback LLStoreAssetCallback;
typedef ::LLGetAssetCallback LLGetAssetCallback; typedef ::LLGetAssetCallback LLGetAssetCallback;
@ -230,11 +225,9 @@ protected:
toxic_asset_map_t mToxicAssetMap; // Objects in this list are known to cause problems and are not loaded toxic_asset_map_t mToxicAssetMap; // Objects in this list are known to cause problems and are not loaded
public: public:
LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, const LLHost &upstream_host);
LLVFS *vfs, LLVFS *static_vfs, const LLHost &upstream_host);
LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, LLAssetStorage(LLMessageSystem *msg, LLXferManager *xfer);
LLVFS *vfs, LLVFS *static_vfs);
virtual ~LLAssetStorage(); virtual ~LLAssetStorage();
void setUpstream(const LLHost &upstream_host); void setUpstream(const LLHost &upstream_host);
@ -284,7 +277,7 @@ public:
void markAssetToxic( const LLUUID& uuid ); void markAssetToxic( const LLUUID& uuid );
protected: protected:
bool findInStaticVFSAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type, bool findInCacheAndInvokeCallback(const LLUUID& uuid, LLAssetType::EType type,
LLGetAssetCallback callback, void *user_data); LLGetAssetCallback callback, void *user_data);
LLSD getPendingDetailsImpl(const request_list_t* requests, LLSD getPendingDetailsImpl(const request_list_t* requests,
@ -375,7 +368,7 @@ public:
bool user_waiting = false, bool user_waiting = false,
F64Seconds timeout = LL_ASSET_STORAGE_TIMEOUT) = 0; F64Seconds timeout = LL_ASSET_STORAGE_TIMEOUT) = 0;
static void legacyGetDataCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType, void *user_data, S32 status, LLExtStat ext_status); static void legacyGetDataCallback(const LLUUID &uuid, LLAssetType::EType, void *user_data, S32 status, LLExtStat ext_status);
static void legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status); static void legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status);
// add extra methods to handle metadata // add extra methods to handle metadata
@ -385,15 +378,12 @@ protected:
void _callUploadCallbacks(const LLUUID &uuid, const LLAssetType::EType asset_type, BOOL success, LLExtStat ext_status); void _callUploadCallbacks(const LLUUID &uuid, const LLAssetType::EType asset_type, BOOL success, LLExtStat ext_status);
virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, LLGetAssetCallback callback, virtual void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, LLGetAssetCallback callback,
// void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat),
void *user_data, BOOL duplicate, void *user_data, BOOL duplicate,
BOOL is_priority) = 0; BOOL is_priority) = 0;
private: private:
void _init(LLMessageSystem *msg, void _init(LLMessageSystem *msg,
LLXferManager *xfer, LLXferManager *xfer,
LLVFS *vfs,
LLVFS *static_vfs,
const LLHost &upstream_host); const LLHost &upstream_host);
protected: protected:
@ -408,7 +398,7 @@ protected:
MR_FILE_NONEXIST = 3, // Old format store call - source file does not exist MR_FILE_NONEXIST = 3, // Old format store call - source file does not exist
MR_NO_FILENAME = 4, // Old format store call - source filename is NULL/0-length MR_NO_FILENAME = 4, // Old format store call - source filename is NULL/0-length
MR_NO_UPSTREAM = 5, // Upstream provider is missing MR_NO_UPSTREAM = 5, // Upstream provider is missing
MR_VFS_CORRUPTION = 6 // VFS is corrupt - too-large or mismatched stated/returned sizes MR_CACHE_CORRUPTION = 6 // cache is corrupt - too-large or mismatched stated/returned sizes
}; };
static class LLMetrics *metric_recipient; static class LLMetrics *metric_recipient;

View File

@ -37,7 +37,7 @@
#include "llsdserialize.h" #include "llsdserialize.h"
#include "reader.h" // JSON #include "reader.h" // JSON
#include "writer.h" // JSON #include "writer.h" // JSON
#include "llvfile.h" #include "llfilesystem.h"
#include "message.h" // for getting the port #include "message.h" // for getting the port
@ -784,7 +784,7 @@ LLSD HttpCoroutineAdapter::postFileAndSuspend(LLCore::HttpRequest::ptr_t request
// scoping for our streams so that they go away when we no longer need them. // scoping for our streams so that they go away when we no longer need them.
{ {
LLCore::BufferArrayStream outs(fileData.get()); LLCore::BufferArrayStream outs(fileData.get());
LLVFile vfile(gVFS, assetId, assetType, LLVFile::READ); LLFileSystem vfile(assetId, assetType, LLFileSystem::READ);
S32 fileSize = vfile.getSize(); S32 fileSize = vfile.getSize();
U8* fileBuffer; U8* fileBuffer;

View File

@ -1,7 +1,7 @@
/** /**
* @file llextendedstatus.h * @file llextendedstatus.h
* @date August 2007 * @date August 2007
* @brief extended status codes for curl/vfs/resident asset storage and delivery * @brief extended status codes for curl/resident asset storage and delivery
* *
* $LicenseInfo:firstyear=2007&license=viewerlgpl$ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code * Second Life Viewer Source Code
@ -32,9 +32,9 @@ enum class LLExtStat: uint32_t
{ {
// Status provider groups - Top bits indicate which status type it is // Status provider groups - Top bits indicate which status type it is
// Zero is common status code (next section) // Zero is common status code (next section)
CURL_RESULT = 1UL<<30, // serviced by curl - use 1L if we really implement the below CURL_RESULT = 1UL<<30, // serviced by curl - use 1L if we really implement the below
RES_RESULT = 2UL<<30, // serviced by resident copy RES_RESULT = 2UL<<30, // serviced by resident copy
VFS_RESULT = 3UL<<30, // serviced by vfs CACHE_RESULT = 3UL<<30, // serviced by cache
// Common Status Codes // Common Status Codes
@ -54,9 +54,9 @@ enum class LLExtStat: uint32_t
// Memory-Resident status codes: // Memory-Resident status codes:
// None at present // None at present
// VFS status codes: // CACHE status codes:
VFS_CACHED = VFS_RESULT | 0x0001, CACHE_CACHED = CACHE_RESULT | 0x0001,
VFS_CORRUPT = VFS_RESULT | 0x0002, CACHE_CORRUPT = CACHE_RESULT | 0x0002,
}; };

View File

@ -32,7 +32,7 @@
#include "message.h" #include "message.h"
#include "lldatapacker.h" #include "lldatapacker.h"
#include "lldir.h" #include "lldir.h"
#include "llvfile.h" #include "llfilesystem.h"
LLTransferSourceAsset::LLTransferSourceAsset(const LLUUID &request_id, const F32 priority) : LLTransferSourceAsset::LLTransferSourceAsset(const LLUUID &request_id, const F32 priority) :
LLTransferSource(LLTST_ASSET, request_id, priority), LLTransferSource(LLTST_ASSET, request_id, priority),
@ -99,7 +99,7 @@ LLTSCode LLTransferSourceAsset::dataCallback(const S32 packet_id,
return LLTS_SKIP; return LLTS_SKIP;
} }
LLVFile vf(gAssetStorage->mVFS, mParams.getAssetID(), mParams.getAssetType(), LLVFile::READ); LLFileSystem vf(mParams.getAssetID(), mParams.getAssetType(), LLFileSystem::READ);
if (!vf.getSize()) if (!vf.getSize())
{ {
@ -171,7 +171,7 @@ BOOL LLTransferSourceAsset::unpackParams(LLDataPacker &dp)
} }
void LLTransferSourceAsset::responderCallback(LLVFS *vfs, const LLUUID& uuid, LLAssetType::EType type, void LLTransferSourceAsset::responderCallback(const LLUUID& uuid, LLAssetType::EType type,
void *user_data, S32 result, LLExtStat ext_status ) void *user_data, S32 result, LLExtStat ext_status )
{ {
LLUUID *tidp = ((LLUUID*) user_data); LLUUID *tidp = ((LLUUID*) user_data);
@ -198,7 +198,7 @@ void LLTransferSourceAsset::responderCallback(LLVFS *vfs, const LLUUID& uuid, LL
if (LL_ERR_NOERR == result) if (LL_ERR_NOERR == result)
{ {
// Everything's OK. // Everything's OK.
LLVFile vf(gAssetStorage->mVFS, uuid, type, LLVFile::READ); LLFileSystem vf(uuid, type, LLFileSystem::READ);
tsap->mSize = vf.getSize(); tsap->mSize = vf.getSize();
status = LLTS_OK; status = LLTS_OK;
} }

View File

@ -30,7 +30,7 @@
#include "lltransfermanager.h" #include "lltransfermanager.h"
#include "llassetstorage.h" #include "llassetstorage.h"
class LLVFile; class LLFileSystem;
class LLTransferSourceParamsAsset : public LLTransferSourceParams class LLTransferSourceParamsAsset : public LLTransferSourceParams
{ {
@ -56,7 +56,7 @@ public:
LLTransferSourceAsset(const LLUUID &request_id, const F32 priority); LLTransferSourceAsset(const LLUUID &request_id, const F32 priority);
virtual ~LLTransferSourceAsset(); virtual ~LLTransferSourceAsset();
static void responderCallback(LLVFS *vfs, const LLUUID& uuid, LLAssetType::EType type, static void responderCallback(const LLUUID& uuid, LLAssetType::EType type,
void *user_data, S32 result, LLExtStat ext_status ); void *user_data, S32 result, LLExtStat ext_status );
protected: protected:
/*virtual*/ void initTransfer(); /*virtual*/ void initTransfer();

View File

@ -30,7 +30,7 @@
#include "lldatapacker.h" #include "lldatapacker.h"
#include "llerror.h" #include "llerror.h"
#include "llvfile.h" #include "llfilesystem.h"
//static //static
void LLTransferTargetVFile::updateQueue(bool shutdown) void LLTransferTargetVFile::updateQueue(bool shutdown)
@ -138,10 +138,9 @@ LLTSCode LLTransferTargetVFile::dataCallback(const S32 packet_id, U8 *in_datap,
//LL_INFOS() << "LLTransferTargetFile::dataCallback" << LL_ENDL; //LL_INFOS() << "LLTransferTargetFile::dataCallback" << LL_ENDL;
//LL_INFOS() << "Packet: " << packet_id << LL_ENDL; //LL_INFOS() << "Packet: " << packet_id << LL_ENDL;
LLVFile vf(gAssetStorage->mVFS, mTempID, mParams.getAssetType(), LLVFile::APPEND); LLFileSystem vf(mTempID, mParams.getAssetType(), LLFileSystem::APPEND);
if (mNeedsCreate) if (mNeedsCreate)
{ {
vf.setMaxSize(mSize);
mNeedsCreate = FALSE; mNeedsCreate = FALSE;
} }
@ -176,7 +175,7 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status)
case LLTS_DONE: case LLTS_DONE:
if (!mNeedsCreate) if (!mNeedsCreate)
{ {
LLVFile file(gAssetStorage->mVFS, mTempID, mParams.getAssetType(), LLVFile::WRITE); LLFileSystem file(mTempID, mParams.getAssetType(), LLFileSystem::WRITE);
if (!file.rename(mParams.getAssetID(), mParams.getAssetType())) if (!file.rename(mParams.getAssetID(), mParams.getAssetType()))
{ {
LL_ERRS() << "LLTransferTargetVFile: rename failed" << LL_ENDL; LL_ERRS() << "LLTransferTargetVFile: rename failed" << LL_ENDL;
@ -195,7 +194,7 @@ void LLTransferTargetVFile::completionCallback(const LLTSCode status)
{ {
// We're aborting this transfer, we don't want to keep this file. // We're aborting this transfer, we don't want to keep this file.
LL_WARNS() << "Aborting vfile transfer for " << mParams.getAssetID() << LL_ENDL; LL_WARNS() << "Aborting vfile transfer for " << mParams.getAssetID() << LL_ENDL;
LLVFile vf(gAssetStorage->mVFS, mTempID, mParams.getAssetType(), LLVFile::APPEND); LLFileSystem vf(mTempID, mParams.getAssetType(), LLFileSystem::APPEND);
vf.remove(); vf.remove();
} }
break; break;

View File

@ -29,9 +29,9 @@
#include "lltransfermanager.h" #include "lltransfermanager.h"
#include "llassetstorage.h" #include "llassetstorage.h"
#include "llvfile.h" #include "llfilesystem.h"
class LLVFile; class LLFileSystem;
// Lame, an S32 for now until I figure out the deal with how we want to do // Lame, an S32 for now until I figure out the deal with how we want to do
// error codes. // error codes.

View File

@ -30,8 +30,7 @@
#include "lluuid.h" #include "lluuid.h"
#include "llerror.h" #include "llerror.h"
#include "llmath.h" #include "llmath.h"
#include "llvfile.h" #include "llfilesystem.h"
#include "llvfs.h"
#include "lldir.h" #include "lldir.h"
// size of chunks read from/written to disk // size of chunks read from/written to disk
@ -42,13 +41,13 @@ const U32 LL_MAX_XFER_FILE_BUFFER = 65536;
LLXfer_VFile::LLXfer_VFile () LLXfer_VFile::LLXfer_VFile ()
: LLXfer(-1) : LLXfer(-1)
{ {
init(NULL, LLUUID::null, LLAssetType::AT_NONE); init(LLUUID::null, LLAssetType::AT_NONE);
} }
LLXfer_VFile::LLXfer_VFile (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type) LLXfer_VFile::LLXfer_VFile (const LLUUID &local_id, LLAssetType::EType type)
: LLXfer(-1) : LLXfer(-1)
{ {
init(vfs, local_id, type); init(local_id, type);
} }
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -60,10 +59,8 @@ LLXfer_VFile::~LLXfer_VFile ()
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
void LLXfer_VFile::init (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type) void LLXfer_VFile::init (const LLUUID &local_id, LLAssetType::EType type)
{ {
mVFS = vfs;
mLocalID = local_id; mLocalID = local_id;
mType = type; mType = type;
@ -82,14 +79,14 @@ void LLXfer_VFile::cleanup ()
if (mTempID.notNull() && if (mTempID.notNull() &&
mDeleteTempFile) mDeleteTempFile)
{ {
if (mVFS->getExists(mTempID, mType)) if (LLFileSystem::getExists(mTempID, mType))
{ {
LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE); LLFileSystem file(mTempID, mType, LLFileSystem::WRITE);
file.remove(); file.remove();
} }
else else
{ {
LL_WARNS("Xfer") << "LLXfer_VFile::cleanup() can't open to delete VFS file " << mTempID << "." << LLAssetType::lookup(mType) LL_WARNS("Xfer") << "LLXfer_VFile::cleanup() can't open to delete cache file " << mTempID << "." << LLAssetType::lookup(mType)
<< ", mRemoteID is " << mRemoteID << LL_ENDL; << ", mRemoteID is " << mRemoteID << LL_ENDL;
} }
} }
@ -103,7 +100,6 @@ void LLXfer_VFile::cleanup ()
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
S32 LLXfer_VFile::initializeRequest(U64 xfer_id, S32 LLXfer_VFile::initializeRequest(U64 xfer_id,
LLVFS* vfs,
const LLUUID& local_id, const LLUUID& local_id,
const LLUUID& remote_id, const LLUUID& remote_id,
LLAssetType::EType type, LLAssetType::EType type,
@ -115,7 +111,6 @@ S32 LLXfer_VFile::initializeRequest(U64 xfer_id,
mRemoteHost = remote_host; mRemoteHost = remote_host;
mVFS = vfs;
mLocalID = local_id; mLocalID = local_id;
mRemoteID = remote_id; mRemoteID = remote_id;
mType = type; mType = type;
@ -192,13 +187,13 @@ S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host)
delete mVFile; delete mVFile;
mVFile = NULL; mVFile = NULL;
if(mVFS->getExists(mLocalID, mType)) if(LLFileSystem::getExists(mLocalID, mType))
{ {
mVFile = new LLVFile(mVFS, mLocalID, mType, LLVFile::READ); mVFile = new LLFileSystem(mLocalID, mType, LLFileSystem::READ);
if (mVFile->getSize() <= 0) if (mVFile->getSize() <= 0)
{ {
LL_WARNS("Xfer") << "LLXfer_VFile::startSend() VFS file " << mLocalID << "." << LLAssetType::lookup(mType) LL_WARNS("Xfer") << "LLXfer_VFile::startSend() cache file " << mLocalID << "." << LLAssetType::lookup(mType)
<< " has unexpected file size of " << mVFile->getSize() << LL_ENDL; << " has unexpected file size of " << mVFile->getSize() << LL_ENDL;
delete mVFile; delete mVFile;
mVFile = NULL; mVFile = NULL;
@ -214,7 +209,7 @@ S32 LLXfer_VFile::startSend (U64 xfer_id, const LLHost &remote_host)
} }
else else
{ {
LL_WARNS("Xfer") << "LLXfer_VFile::startSend() can't read VFS file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL; LL_WARNS("Xfer") << "LLXfer_VFile::startSend() can't read cache file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL;
retval = LL_ERR_FILE_NOT_FOUND; retval = LL_ERR_FILE_NOT_FOUND;
} }
@ -240,13 +235,13 @@ S32 LLXfer_VFile::reopenFileHandle()
if (mVFile == NULL) if (mVFile == NULL)
{ {
if (mVFS->getExists(mLocalID, mType)) if (LLFileSystem::getExists(mLocalID, mType))
{ {
mVFile = new LLVFile(mVFS, mLocalID, mType, LLVFile::READ); mVFile = new LLFileSystem(mLocalID, mType, LLFileSystem::READ);
} }
else else
{ {
LL_WARNS("Xfer") << "LLXfer_VFile::reopenFileHandle() can't read VFS file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL; LL_WARNS("Xfer") << "LLXfer_VFile::reopenFileHandle() can't read cache file " << mLocalID << "." << LLAssetType::lookup(mType) << LL_ENDL;
retval = LL_ERR_FILE_NOT_FOUND; retval = LL_ERR_FILE_NOT_FOUND;
} }
} }
@ -265,8 +260,7 @@ void LLXfer_VFile::setXferSize (S32 xfer_size)
// It would be nice if LLXFers could tell which end of the pipe they were // It would be nice if LLXFers could tell which end of the pipe they were
if (! mVFile) if (! mVFile)
{ {
LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND); LLFileSystem file(mTempID, mType, LLFileSystem::APPEND);
file.setMaxSize(xfer_size);
} }
} }
@ -320,7 +314,7 @@ S32 LLXfer_VFile::flush()
S32 retval = 0; S32 retval = 0;
if (mBufferLength) if (mBufferLength)
{ {
LLVFile file(mVFS, mTempID, mType, LLVFile::APPEND); LLFileSystem file(mTempID, mType, LLFileSystem::APPEND);
file.write((U8*)mBuffer, mBufferLength); file.write((U8*)mBuffer, mBufferLength);
@ -340,22 +334,15 @@ S32 LLXfer_VFile::processEOF()
if (!mCallbackResult) if (!mCallbackResult)
{ {
if (mVFS->getExists(mTempID, mType)) if (LLFileSystem::getExists(mTempID, mType))
{ {
LLVFile file(mVFS, mTempID, mType, LLVFile::WRITE); LLFileSystem file(mTempID, mType, LLFileSystem::WRITE);
if (!file.rename(mLocalID, mType)) if (!file.rename(mLocalID, mType))
{ {
LL_WARNS("Xfer") << "VFS rename of temp file failed: unable to rename " << mTempID << " to " << mLocalID << LL_ENDL; LL_WARNS("Xfer") << "Cache rename of temp file failed: unable to rename " << mTempID << " to " << mLocalID << LL_ENDL;
} }
else else
{ {
#ifdef VFS_SPAM
// Debugging spam
LL_INFOS("Xfer") << "VFS rename of temp file done: renamed " << mTempID << " to " << mLocalID
<< " LLVFile size is " << file.getSize()
<< LL_ENDL;
#endif
// Rename worked: the original file is gone. Clear mDeleteTempFile // Rename worked: the original file is gone. Clear mDeleteTempFile
// so we don't attempt to delete the file in cleanup() // so we don't attempt to delete the file in cleanup()
mDeleteTempFile = FALSE; mDeleteTempFile = FALSE;
@ -363,7 +350,7 @@ S32 LLXfer_VFile::processEOF()
} }
else else
{ {
LL_WARNS("Xfer") << "LLXfer_VFile::processEOF() can't open for renaming VFS file " << mTempID << "." << LLAssetType::lookup(mType) << LL_ENDL; LL_WARNS("Xfer") << "LLXfer_VFile::processEOF() can't open for renaming cache file " << mTempID << "." << LLAssetType::lookup(mType) << LL_ENDL;
} }
} }

View File

@ -30,8 +30,7 @@
#include "llxfer.h" #include "llxfer.h"
#include "llassetstorage.h" #include "llassetstorage.h"
class LLVFS; class LLFileSystem;
class LLVFile;
class LLXfer_VFile : public LLXfer class LLXfer_VFile : public LLXfer
{ {
@ -41,9 +40,7 @@ class LLXfer_VFile : public LLXfer
LLUUID mTempID; LLUUID mTempID;
LLAssetType::EType mType; LLAssetType::EType mType;
LLVFile *mVFile; LLFileSystem *mVFile;
LLVFS *mVFS;
std::string mName; std::string mName;
@ -51,14 +48,13 @@ class LLXfer_VFile : public LLXfer
public: public:
LLXfer_VFile (); LLXfer_VFile ();
LLXfer_VFile (LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type); LLXfer_VFile (const LLUUID &local_id, LLAssetType::EType type);
virtual ~LLXfer_VFile(); virtual ~LLXfer_VFile();
virtual void init(LLVFS *vfs, const LLUUID &local_id, LLAssetType::EType type); virtual void init(const LLUUID &local_id, LLAssetType::EType type);
virtual void cleanup(); virtual void cleanup();
virtual S32 initializeRequest(U64 xfer_id, virtual S32 initializeRequest(U64 xfer_id,
LLVFS *vfs,
const LLUUID &local_id, const LLUUID &local_id,
const LLUUID &remote_id, const LLUUID &remote_id,
const LLAssetType::EType type, const LLAssetType::EType type,

View File

@ -56,9 +56,9 @@ const S32 LL_DEFAULT_MAX_HARD_LIMIT_SIMULTANEOUS_XFERS = 500;
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
LLXferManager::LLXferManager (LLVFS *vfs) LLXferManager::LLXferManager ()
{ {
init(vfs); init();
} }
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
@ -70,7 +70,7 @@ LLXferManager::~LLXferManager ()
/////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////
void LLXferManager::init (LLVFS *vfs) void LLXferManager::init()
{ {
cleanup(); cleanup();
@ -78,8 +78,6 @@ void LLXferManager::init (LLVFS *vfs)
setHardLimitOutgoingXfersPerCircuit(LL_DEFAULT_MAX_HARD_LIMIT_SIMULTANEOUS_XFERS); setHardLimitOutgoingXfersPerCircuit(LL_DEFAULT_MAX_HARD_LIMIT_SIMULTANEOUS_XFERS);
setMaxIncomingXfers(LL_DEFAULT_MAX_REQUEST_FIFO_XFERS); setMaxIncomingXfers(LL_DEFAULT_MAX_REQUEST_FIFO_XFERS);
mVFS = vfs;
// Turn on or off ack throttling // Turn on or off ack throttling
mUseAckThrottling = FALSE; mUseAckThrottling = FALSE;
setAckThrottleBPS(100000); setAckThrottleBPS(100000);
@ -462,7 +460,7 @@ U64 LLXferManager::requestFile(const std::string& local_filename,
void LLXferManager::requestVFile(const LLUUID& local_id, void LLXferManager::requestVFile(const LLUUID& local_id,
const LLUUID& remote_id, const LLUUID& remote_id,
LLAssetType::EType type, LLVFS* vfs, LLAssetType::EType type,
const LLHost& remote_host, const LLHost& remote_host,
void (*callback)(void**,S32,LLExtStat), void (*callback)(void**,S32,LLExtStat),
void** user_data, void** user_data,
@ -508,7 +506,6 @@ void LLXferManager::requestVFile(const LLUUID& local_id,
addToList(xfer_p, mReceiveList, is_priority); addToList(xfer_p, mReceiveList, is_priority);
((LLXfer_VFile *)xfer_p)->initializeRequest(getNextID(), ((LLXfer_VFile *)xfer_p)->initializeRequest(getNextID(),
vfs,
local_id, local_id,
remote_id, remote_id,
type, type,
@ -784,33 +781,17 @@ void LLXferManager::processFileRequest (LLMessageSystem *mesgsys, void ** /*user
LLXfer *xferp; LLXfer *xferp;
if (uuid != LLUUID::null) if (uuid != LLUUID::null)
{ // Request for an asset - use a VFS file { // Request for an asset - use a cache file
if(NULL == LLAssetType::lookup(type)) if(NULL == LLAssetType::lookup(type))
{ {
LL_WARNS("Xfer") << "Invalid type for xfer request: " << uuid << ":" LL_WARNS("Xfer") << "Invalid type for xfer request: " << uuid << ":"
<< type_s16 << " to " << mesgsys->getSender() << LL_ENDL; << type_s16 << " to " << mesgsys->getSender() << LL_ENDL;
return; return;
} }
if (! mVFS)
{
LL_WARNS("Xfer") << "Attempt to send VFile w/o available VFS" << LL_ENDL;
return;
}
/* Present in fireengine, not used by viewer
if (!validateVFileForTransfer(uuid.asString()))
{
// it is up to the app sending the file to mark it for expected
// transfer before the request arrives or it will be dropped
LL_WARNS("Xfer") << "SECURITY: Unapproved VFile '" << uuid << "'" << LL_ENDL;
return;
}
*/
LL_INFOS("Xfer") << "starting vfile transfer: " << uuid << "," << LLAssetType::lookup(type) << " to " << mesgsys->getSender() << LL_ENDL; LL_INFOS("Xfer") << "starting vfile transfer: " << uuid << "," << LLAssetType::lookup(type) << " to " << mesgsys->getSender() << LL_ENDL;
xferp = (LLXfer *)new LLXfer_VFile(mVFS, uuid, type); xferp = (LLXfer *)new LLXfer_VFile(uuid, type);
if (xferp) if (xferp)
{ {
mSendList.push_front(xferp); mSendList.push_front(xferp);
@ -1273,9 +1254,9 @@ void LLXferManager::addToList(LLXfer* xferp, xfer_list_t & xfer_list, BOOL is_pr
LLXferManager *gXferManager = NULL; LLXferManager *gXferManager = NULL;
void start_xfer_manager(LLVFS *vfs) void start_xfer_manager()
{ {
gXferManager = new LLXferManager(vfs); gXferManager = new LLXferManager();
} }
void cleanup_xfer_manager() void cleanup_xfer_manager()

View File

@ -35,7 +35,6 @@
//Forward declaration to avoid circular dependencies //Forward declaration to avoid circular dependencies
class LLXfer; class LLXfer;
class LLVFS;
#include "llxfer.h" #include "llxfer.h"
#include "message.h" #include "message.h"
@ -72,9 +71,6 @@ public:
class LLXferManager class LLXferManager
{ {
private:
LLVFS *mVFS;
protected: protected:
S32 mMaxOutgoingXfersPerCircuit; S32 mMaxOutgoingXfersPerCircuit;
S32 mHardLimitOutgoingXfersPerCircuit; // At this limit, kill off the connection S32 mHardLimitOutgoingXfersPerCircuit; // At this limit, kill off the connection
@ -111,10 +107,10 @@ class LLXferManager
std::multiset<std::string> mExpectedVFileRequests; // files that are authorized to be downloaded on top of std::multiset<std::string> mExpectedVFileRequests; // files that are authorized to be downloaded on top of
public: public:
LLXferManager(LLVFS *vfs); LLXferManager();
virtual ~LLXferManager(); virtual ~LLXferManager();
virtual void init(LLVFS *vfs); virtual void init();
virtual void cleanup(); virtual void cleanup();
void setUseAckThrottling(const BOOL use); void setUseAckThrottling(const BOOL use);
@ -166,7 +162,7 @@ class LLXferManager
// vfile requesting // vfile requesting
// .. to vfile // .. to vfile
virtual void requestVFile(const LLUUID &local_id, const LLUUID& remote_id, virtual void requestVFile(const LLUUID &local_id, const LLUUID& remote_id,
LLAssetType::EType type, LLVFS* vfs, LLAssetType::EType type,
const LLHost& remote_host, const LLHost& remote_host,
void (*callback)(void**,S32,LLExtStat), void** user_data, void (*callback)(void**,S32,LLExtStat), void** user_data,
BOOL is_priority = FALSE); BOOL is_priority = FALSE);
@ -213,7 +209,7 @@ class LLXferManager
extern LLXferManager* gXferManager; extern LLXferManager* gXferManager;
// initialization and garbage collection // initialization and garbage collection
void start_xfer_manager(LLVFS *vfs); void start_xfer_manager();
void cleanup_xfer_manager(); void cleanup_xfer_manager();
// message system callbacks // message system callbacks

View File

@ -46,6 +46,7 @@
#include "apr_poll.h" #include "apr_poll.h"
// linden library headers // linden library headers
#include "llapp.h"
#include "indra_constants.h" #include "indra_constants.h"
#include "lldir.h" #include "lldir.h"
#include "llerror.h" #include "llerror.h"

View File

@ -774,6 +774,15 @@ void LLPluginClassMedia::loadURI(const std::string &uri)
sendMessage(message); sendMessage(message);
} }
void LLPluginClassMedia::executeJavaScript(const std::string &code)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "execute_javascript");
message.setValue("code", code);
sendMessage(message);
}
const char* LLPluginClassMedia::priorityToString(EPriority priority) const char* LLPluginClassMedia::priorityToString(EPriority priority)
{ {
const char* result = "UNKNOWN"; const char* result = "UNKNOWN";
@ -951,6 +960,19 @@ void LLPluginClassMedia::setJavascriptEnabled(const bool enabled)
sendMessage(message); sendMessage(message);
} }
void LLPluginClassMedia::setWebSecurityDisabled(const bool disabled)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "web_security_disabled");
message.setValueBoolean("disabled", disabled);
sendMessage(message);
}
void LLPluginClassMedia::setFileAccessFromFileUrlsEnabled(const bool enabled)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "file_access_from_file_urls");
message.setValueBoolean("enabled", enabled);
sendMessage(message);
}
void LLPluginClassMedia::enableMediaPluginDebugging( bool enable ) void LLPluginClassMedia::enableMediaPluginDebugging( bool enable )
{ {

View File

@ -153,6 +153,8 @@ public:
void loadURI(const std::string &uri); void loadURI(const std::string &uri);
void executeJavaScript(const std::string &code);
// "Loading" means uninitialized or any state prior to fully running (processing commands) // "Loading" means uninitialized or any state prior to fully running (processing commands)
bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; }; bool isPluginLoading(void) { return mPlugin?mPlugin->isLoading():false; };
@ -213,6 +215,8 @@ public:
void setLanguageCode(const std::string &language_code); void setLanguageCode(const std::string &language_code);
void setPluginsEnabled(const bool enabled); void setPluginsEnabled(const bool enabled);
void setJavascriptEnabled(const bool enabled); void setJavascriptEnabled(const bool enabled);
void setWebSecurityDisabled(const bool disabled);
void setFileAccessFromFileUrlsEnabled(const bool enabled);
void setTarget(const std::string &target); void setTarget(const std::string &target);
/////////////////////////////////// ///////////////////////////////////

View File

@ -28,6 +28,7 @@
#include "linden_common.h" #include "linden_common.h"
#include "llapp.h"
#include "llpluginprocessparent.h" #include "llpluginprocessparent.h"
#include "llpluginmessagepipe.h" #include "llpluginmessagepipe.h"
#include "llpluginmessageclasses.h" #include "llpluginmessageclasses.h"

View File

@ -9,10 +9,9 @@ include(LLCommon)
include(LLImage) include(LLImage)
include(LLMath) include(LLMath)
include(LLRender) include(LLRender)
include(LLVFS)
include(LLWindow) include(LLWindow)
include(LLXML) include(LLXML)
include(LLVFS) include(LLFileSystem)
include_directories( include_directories(
${FREETYPE_INCLUDE_DIRS} ${FREETYPE_INCLUDE_DIRS}
@ -20,10 +19,9 @@ include_directories(
${LLIMAGE_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS}
) )
include_directories(SYSTEM include_directories(SYSTEM
${LLCOMMON_SYSTEM_INCLUDE_DIRS} ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@ -104,9 +102,8 @@ if (BUILD_HEADLESS)
${LLIMAGE_LIBRARIES} ${LLIMAGE_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLRENDER_HEADLESS_LIBRARIES} ${LLRENDER_HEADLESS_LIBRARIES}
${LLVFS_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLWINDOW_HEADLESS_LIBRARIES} ${LLWINDOW_HEADLESS_LIBRARIES}
${OPENGL_HEADLESS_LIBRARIES}) ${OPENGL_HEADLESS_LIBRARIES})
@ -126,9 +123,8 @@ target_link_libraries(llrender
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${LLIMAGE_LIBRARIES} ${LLIMAGE_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
${LLVFS_LIBRARIES}
${LLWINDOW_LIBRARIES} ${LLWINDOW_LIBRARIES}
${FREETYPE_LIBRARIES} ${FREETYPE_LIBRARIES}
${OPENGL_LIBRARIES}) ${OPENGL_LIBRARIES})

View File

@ -13,7 +13,7 @@ include(LLCoreHttp)
include(LLRender) include(LLRender)
include(LLWindow) include(LLWindow)
include(LLCoreHttp) include(LLCoreHttp)
include(LLVFS) include(LLFileSystem)
include(LLXML) include(LLXML)
include_directories( include_directories(
@ -25,7 +25,7 @@ include_directories(
${LLMESSAGE_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS}
${LIBS_PREBUILD_DIR}/include/hunspell ${LIBS_PREBUILD_DIR}/include/hunspell
) )
@ -285,7 +285,7 @@ target_link_libraries(llui
${LLINVENTORY_LIBRARIES} ${LLINVENTORY_LIBRARIES}
${LLMESSAGE_LIBRARIES} ${LLMESSAGE_LIBRARIES}
${LLCOREHTTP_LIBRARIES} ${LLCOREHTTP_LIBRARIES}
${LLVFS_LIBRARIES} # ugh, just for LLDir ${LLFILESYSTEM_LIBRARIES}
${LLXUIXML_LIBRARIES} ${LLXUIXML_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}

View File

@ -32,7 +32,6 @@
#include "lldir.h" #include "lldir.h"
#include "llsd.h" #include "llsd.h"
#include "llfile.h" #include "llfile.h"
#include "llvfile.h"
#include "lldate.h" #include "lldate.h"
#include "llsdserialize.h" #include "llsdserialize.h"
#include "llkeyboard.h" #include "llkeyboard.h"

View File

@ -1,276 +0,0 @@
/**
* @file llformat.cpp
* @date January 2007
* @brief string formatting utility
*
* $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llapr.h" // thread-related functions
#include "llpidlock.h"
#include "lldir.h"
#include "llsd.h"
#include "llsdserialize.h"
#include "llnametable.h"
#include "llframetimer.h"
#if LL_WINDOWS //For windows platform.
#include <windows.h>
bool isProcessAlive(U32 pid)
{
return (bool) GetProcessVersion((DWORD)pid);
}
#else //Everyone Else
bool isProcessAlive(U32 pid)
{
return (bool) kill( (pid_t)pid, 0);
}
#endif //Everyone else.
class LLPidLockFile
{
public:
LLPidLockFile( ) :
mAutosave(false),
mSaving(false),
mWaiting(false),
mPID(getpid()),
mNameTable(NULL),
mClean(true)
{
mLockName = gDirUtilp->getTempDir() + gDirUtilp->getDirDelimiter() + "savelock";
}
bool requestLock(LLNameTable<void *> *name_table, bool autosave,
bool force_immediate=FALSE, F32 timeout=300.0);
bool checkLock();
void releaseLock();
private:
void writeLockFile(LLSD pids);
public:
static LLPidLockFile& instance(); // return the singleton black list file
bool mAutosave;
bool mSaving;
bool mWaiting;
LLFrameTimer mTimer;
U32 mPID;
std::string mLockName;
std::string mSaveName;
LLSD mPIDS_sd;
LLNameTable<void*> *mNameTable;
bool mClean;
};
LLPidLockFile& LLPidLockFile::instance()
{
static LLPidLockFile the_file;
return the_file;
}
void LLPidLockFile::writeLockFile(LLSD pids)
{
llofstream ofile(mLockName.c_str());
if (!LLSDSerialize::toXML(pids,ofile))
{
LL_WARNS() << "Unable to write concurrent save lock file." << LL_ENDL;
}
ofile.close();
}
bool LLPidLockFile::requestLock(LLNameTable<void *> *name_table, bool autosave,
bool force_immediate, F32 timeout)
{
bool readyToSave = FALSE;
if (mSaving) return FALSE; //Bail out if we're currently saving. Will not queue another save.
if (!mWaiting){
mNameTable=name_table;
mAutosave = autosave;
}
LLSD out_pids;
out_pids.append( (LLSD::Integer)mPID );
llifstream ifile(mLockName.c_str());
if (ifile.is_open())
{ //If file exists, we need to decide whether or not to continue.
if ( force_immediate
|| mTimer.hasExpired() ) //Only deserialize if we REALLY need to.
{
LLSD in_pids;
LLSDSerialize::fromXML(in_pids, ifile);
//Clean up any dead PIDS that might be in there.
for (LLSD::array_iterator i=in_pids.beginArray();
i !=in_pids.endArray();
++i)
{
U32 stored_pid=(*i).asInteger();
if (isProcessAlive(stored_pid))
{
out_pids.append( (*i) );
}
}
readyToSave=TRUE;
}
ifile.close();
}
else
{
readyToSave=TRUE;
}
if (!mWaiting) //Not presently waiting to save. Queue up.
{
mTimer.resetWithExpiry(timeout);
mWaiting=TRUE;
}
if (readyToSave)
{ //Potential race condition won't kill us. Ignore it.
writeLockFile(out_pids);
mSaving=TRUE;
}
return readyToSave;
}
bool LLPidLockFile::checkLock()
{
return mWaiting;
}
void LLPidLockFile::releaseLock()
{
llifstream ifile(mLockName.c_str());
LLSD in_pids;
LLSD out_pids;
bool write_file=FALSE;
LLSDSerialize::fromXML(in_pids, ifile);
//Clean up this PID and any dead ones.
for (LLSD::array_iterator i=in_pids.beginArray();
i !=in_pids.endArray();
++i)
{
U32 stored_pid=(*i).asInteger();
if (stored_pid != mPID && isProcessAlive(stored_pid))
{
out_pids.append( (*i) );
write_file=TRUE;
}
}
ifile.close();
if (write_file)
{
writeLockFile(out_pids);
}
else
{
unlink(mLockName.c_str());
}
mSaving=FALSE;
mWaiting=FALSE;
}
//LLPidLock
void LLPidLock::initClass() {
(void) LLPidLockFile::instance();
}
bool LLPidLock::checkLock()
{
return LLPidLockFile::instance().checkLock();
}
bool LLPidLock::requestLock(LLNameTable<void *> *name_table, bool autosave,
bool force_immediate, F32 timeout)
{
return LLPidLockFile::instance().requestLock(name_table,autosave,force_immediate,timeout);
}
void LLPidLock::releaseLock()
{
return LLPidLockFile::instance().releaseLock();
}
bool LLPidLock::isClean()
{
return LLPidLockFile::instance().mClean;
}
//getters
LLNameTable<void *> * LLPidLock::getNameTable()
{
return LLPidLockFile::instance().mNameTable;
}
bool LLPidLock::getAutosave()
{
return LLPidLockFile::instance().mAutosave;
}
bool LLPidLock::getClean()
{
return LLPidLockFile::instance().mClean;
}
std::string LLPidLock::getSaveName()
{
return LLPidLockFile::instance().mSaveName;
}
//setters
void LLPidLock::setClean(bool clean)
{
LLPidLockFile::instance().mClean=clean;
}
void LLPidLock::setSaveName(std::string savename)
{
LLPidLockFile::instance().mSaveName=savename;
}
S32 LLPidLock::getPID()
{
return (S32)getpid();
}

View File

@ -1,60 +0,0 @@
/**
* @file llpidlock.h
* @brief System information debugging classes.
*
* $LicenseInfo:firstyear=2001&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$
*/
#ifndef LL_PIDLOCK_H
#define LL_PIDLOCK_H
#include "llnametable.h"
class LLSD;
class LLFrameTimer;
#if !LL_WINDOWS //For non-windows platforms.
#include <signal.h>
#endif
namespace LLPidLock
{
void initClass(); // { (void) LLPidLockFile::instance(); }
bool requestLock( LLNameTable<void *> *name_table=NULL, bool autosave=TRUE,
bool force_immediate=FALSE, F32 timeout=300.0);
bool checkLock();
void releaseLock();
bool isClean();
//getters
LLNameTable<void *> * getNameTable();
bool getAutosave();
bool getClean();
std::string getSaveName();
S32 getPID();
//setters
void setClean(bool clean);
void setSaveName(std::string savename);
};
#endif // LL_PIDLOCK_H

View File

@ -1,437 +0,0 @@
/**
* @file llvfile.cpp
* @brief Implementation of virtual file
*
* $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$
*/
#include "linden_common.h"
#include "llvfile.h"
#include "llerror.h"
#include "llthread.h"
#include "lltimer.h"
#include "llfasttimer.h"
#include "llmemory.h"
#include "llvfs.h"
const S32 LLVFile::READ = 0x00000001;
const S32 LLVFile::WRITE = 0x00000002;
const S32 LLVFile::READ_WRITE = 0x00000003; // LLVFile::READ & LLVFile::WRITE
const S32 LLVFile::APPEND = 0x00000006; // 0x00000004 & LLVFile::WRITE
static LLTrace::BlockTimerStatHandle FTM_VFILE_WAIT("VFile Wait");
//----------------------------------------------------------------------------
LLVFSThread* LLVFile::sVFSThread = NULL;
BOOL LLVFile::sAllocdVFSThread = FALSE;
//----------------------------------------------------------------------------
//============================================================================
LLVFile::LLVFile(LLVFS *vfs, const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode)
{
mFileType = file_type;
mFileID = file_id;
mPosition = 0;
mMode = mode;
mVFS = vfs;
mBytesRead = 0;
mHandle = LLVFSThread::nullHandle();
mPriority = 128.f;
mVFS->incLock(mFileID, mFileType, VFSLOCK_OPEN);
}
LLVFile::~LLVFile()
{
if (!isReadComplete())
{
if (mHandle != LLVFSThread::nullHandle())
{
if (!(mMode & LLVFile::WRITE))
{
//LL_WARNS() << "Destroying LLVFile with pending async read/write, aborting..." << LL_ENDL;
sVFSThread->setFlags(mHandle, LLVFSThread::FLAG_AUTO_COMPLETE | LLVFSThread::FLAG_ABORT);
}
else // WRITE
{
sVFSThread->setFlags(mHandle, LLVFSThread::FLAG_AUTO_COMPLETE);
}
}
}
mVFS->decLock(mFileID, mFileType, VFSLOCK_OPEN);
}
BOOL LLVFile::read(U8 *buffer, S32 bytes, BOOL async, F32 priority)
{
if (! (mMode & READ))
{
LL_WARNS() << "Attempt to read from file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL;
return FALSE;
}
if (mHandle != LLVFSThread::nullHandle())
{
LL_WARNS() << "Attempt to read from vfile object " << mFileID << " with pending async operation" << LL_ENDL;
return FALSE;
}
mPriority = priority;
BOOL success = TRUE;
// We can't do a read while there are pending async writes
waitForLock(VFSLOCK_APPEND);
// *FIX: (?)
if (async)
{
mHandle = sVFSThread->read(mVFS, mFileID, mFileType, buffer, mPosition, bytes, threadPri());
}
else
{
// We can't do a read while there are pending async writes on this file
mBytesRead = sVFSThread->readImmediate(mVFS, mFileID, mFileType, buffer, mPosition, bytes);
mPosition += mBytesRead;
if (! mBytesRead)
{
success = FALSE;
}
}
return success;
}
//static
U8* LLVFile::readFile(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, S32* bytes_read)
{
U8 *data;
LLVFile file(vfs, uuid, type, LLVFile::READ);
S32 file_size = file.getSize();
if (file_size == 0)
{
// File is empty.
data = NULL;
}
else
{
data = (U8*) ll_aligned_malloc<16>(file_size);
file.read(data, file_size); /* Flawfinder: ignore */
if (file.getLastBytesRead() != (S32)file_size)
{
ll_aligned_free<16>(data);
data = NULL;
file_size = 0;
}
}
if (bytes_read)
{
*bytes_read = file_size;
}
return data;
}
void LLVFile::setReadPriority(const F32 priority)
{
mPriority = priority;
if (mHandle != LLVFSThread::nullHandle())
{
sVFSThread->setPriority(mHandle, threadPri());
}
}
BOOL LLVFile::isReadComplete()
{
BOOL res = TRUE;
if (mHandle != LLVFSThread::nullHandle())
{
LLVFSThread::Request* req = (LLVFSThread::Request*)sVFSThread->getRequest(mHandle);
LLVFSThread::status_t status = req->getStatus();
if (status == LLVFSThread::STATUS_COMPLETE)
{
mBytesRead = req->getBytesRead();
mPosition += mBytesRead;
sVFSThread->completeRequest(mHandle);
mHandle = LLVFSThread::nullHandle();
}
else
{
res = FALSE;
}
}
return res;
}
S32 LLVFile::getLastBytesRead()
{
return mBytesRead;
}
BOOL LLVFile::eof()
{
return mPosition >= getSize();
}
BOOL LLVFile::write(const U8 *buffer, S32 bytes)
{
if (! (mMode & WRITE))
{
LL_WARNS() << "Attempt to write to file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL;
}
if (mHandle != LLVFSThread::nullHandle())
{
LL_ERRS() << "Attempt to write to vfile object " << mFileID << " with pending async operation" << LL_ENDL;
return FALSE;
}
BOOL success = TRUE;
// *FIX: allow async writes? potential problem wit mPosition...
if (mMode == APPEND) // all appends are async (but WRITEs are not)
{
U8* writebuf = new U8[bytes];
memcpy(writebuf, buffer, bytes);
S32 offset = -1;
mHandle = sVFSThread->write(mVFS, mFileID, mFileType,
writebuf, offset, bytes,
LLVFSThread::FLAG_AUTO_COMPLETE | LLVFSThread::FLAG_AUTO_DELETE);
mHandle = LLVFSThread::nullHandle(); // FLAG_AUTO_COMPLETE means we don't track this
}
else
{
// We can't do a write while there are pending reads or writes on this file
waitForLock(VFSLOCK_READ);
waitForLock(VFSLOCK_APPEND);
S32 pos = (mMode & APPEND) == APPEND ? -1 : mPosition;
S32 wrote = sVFSThread->writeImmediate(mVFS, mFileID, mFileType, (U8*)buffer, pos, bytes);
mPosition += wrote;
if (wrote < bytes)
{
LL_WARNS() << "Tried to write " << bytes << " bytes, actually wrote " << wrote << LL_ENDL;
success = FALSE;
}
}
return success;
}
//static
BOOL LLVFile::writeFile(const U8 *buffer, S32 bytes, LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type)
{
LLVFile file(vfs, uuid, type, LLVFile::WRITE);
file.setMaxSize(bytes);
return file.write(buffer, bytes);
}
BOOL LLVFile::seek(S32 offset, S32 origin)
{
if (mMode == APPEND)
{
LL_WARNS() << "Attempt to seek on append-only file" << LL_ENDL;
return FALSE;
}
if (-1 == origin)
{
origin = mPosition;
}
S32 new_pos = origin + offset;
S32 size = getSize(); // Calls waitForLock(VFSLOCK_APPEND)
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 = 0;
return FALSE;
}
mPosition = new_pos;
return TRUE;
}
S32 LLVFile::tell() const
{
return mPosition;
}
S32 LLVFile::getSize()
{
waitForLock(VFSLOCK_APPEND);
S32 size = mVFS->getSize(mFileID, mFileType);
return size;
}
S32 LLVFile::getMaxSize()
{
S32 size = mVFS->getMaxSize(mFileID, mFileType);
return size;
}
BOOL LLVFile::setMaxSize(S32 size)
{
if (! (mMode & WRITE))
{
LL_WARNS() << "Attempt to change size of file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL;
return FALSE;
}
if (!mVFS->checkAvailable(size))
{
//LL_RECORD_BLOCK_TIME(FTM_VFILE_WAIT);
S32 count = 0;
while (sVFSThread->getPending() > 1000)
{
if (count % 100 == 0)
{
LL_INFOS() << "VFS catching up... Pending: " << sVFSThread->getPending() << LL_ENDL;
}
if (sVFSThread->isPaused())
{
sVFSThread->update(0);
}
ms_sleep(10);
}
}
return mVFS->setMaxSize(mFileID, mFileType, size);
}
BOOL LLVFile::rename(const LLUUID &new_id, const LLAssetType::EType new_type)
{
if (! (mMode & WRITE))
{
LL_WARNS() << "Attempt to rename file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL;
return FALSE;
}
if (mHandle != LLVFSThread::nullHandle())
{
LL_WARNS() << "Renaming file with pending async read" << LL_ENDL;
}
waitForLock(VFSLOCK_READ);
waitForLock(VFSLOCK_APPEND);
// we need to release / replace our own lock
// since the renamed file will inherit locks from the new name
mVFS->decLock(mFileID, mFileType, VFSLOCK_OPEN);
mVFS->renameFile(mFileID, mFileType, new_id, new_type);
mVFS->incLock(new_id, new_type, VFSLOCK_OPEN);
mFileID = new_id;
mFileType = new_type;
return TRUE;
}
BOOL LLVFile::remove()
{
// LL_INFOS() << "Removing file " << mFileID << LL_ENDL;
if (! (mMode & WRITE))
{
// Leaving paranoia warning just because this should be a very infrequent
// operation.
LL_WARNS() << "Remove file " << mFileID << " opened with mode " << std::hex << mMode << std::dec << LL_ENDL;
}
if (mHandle != LLVFSThread::nullHandle())
{
LL_WARNS() << "Removing file with pending async read" << LL_ENDL;
}
// why not seek back to the beginning of the file too?
mPosition = 0;
waitForLock(VFSLOCK_READ);
waitForLock(VFSLOCK_APPEND);
mVFS->removeFile(mFileID, mFileType);
return TRUE;
}
// static
void LLVFile::initClass(LLVFSThread* vfsthread)
{
if (!vfsthread)
{
if (LLVFSThread::sLocal != NULL)
{
vfsthread = LLVFSThread::sLocal;
}
else
{
vfsthread = new LLVFSThread();
sAllocdVFSThread = TRUE;
}
}
sVFSThread = vfsthread;
}
// static
void LLVFile::cleanupClass()
{
if (sAllocdVFSThread)
{
delete sVFSThread;
}
sVFSThread = NULL;
}
bool LLVFile::isLocked(EVFSLock lock)
{
return mVFS->isLocked(mFileID, mFileType, lock) ? true : false;
}
void LLVFile::waitForLock(EVFSLock lock)
{
//LL_RECORD_BLOCK_TIME(FTM_VFILE_WAIT);
// spin until the lock clears
while (isLocked(lock))
{
if (sVFSThread->isPaused())
{
sVFSThread->update(0);
}
ms_sleep(1);
}
}

View File

@ -1,90 +0,0 @@
/**
* @file llvfile.h
* @brief Definition of virtual file
*
* $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$
*/
#ifndef LL_LLVFILE_H
#define LL_LLVFILE_H
#include "lluuid.h"
#include "llassettype.h"
#include "llvfs.h"
#include "llvfsthread.h"
class LLVFile
{
public:
LLVFile(LLVFS *vfs, const LLUUID &file_id, const LLAssetType::EType file_type, S32 mode = LLVFile::READ);
~LLVFile();
BOOL read(U8 *buffer, S32 bytes, BOOL async = FALSE, F32 priority = 128.f); /* Flawfinder: ignore */
static U8* readFile(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, S32* bytes_read = 0);
void setReadPriority(const F32 priority);
BOOL isReadComplete();
S32 getLastBytesRead();
BOOL eof();
BOOL write(const U8 *buffer, S32 bytes);
static BOOL writeFile(const U8 *buffer, S32 bytes, LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type);
BOOL seek(S32 offset, S32 origin = -1);
S32 tell() const;
S32 getSize();
S32 getMaxSize();
BOOL setMaxSize(S32 size);
BOOL rename(const LLUUID &new_id, const LLAssetType::EType new_type);
BOOL remove();
bool isLocked(EVFSLock lock);
void waitForLock(EVFSLock lock);
static void initClass(LLVFSThread* vfsthread = NULL);
static void cleanupClass();
static LLVFSThread* getVFSThread() { return sVFSThread; }
protected:
static LLVFSThread* sVFSThread;
static BOOL sAllocdVFSThread;
U32 threadPri() { return LLVFSThread::PRIORITY_NORMAL + llmin((U32)mPriority,(U32)0xfff); }
public:
static const S32 READ;
static const S32 WRITE;
static const S32 READ_WRITE;
static const S32 APPEND;
protected:
LLAssetType::EType mFileType;
LLUUID mFileID;
S32 mPosition;
S32 mMode;
LLVFS *mVFS;
F32 mPriority;
S32 mBytesRead;
LLVFSThread::handle_t mHandle;
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,183 +0,0 @@
/**
* @file llvfs.h
* @brief Definition of virtual file system
*
* $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$
*/
#ifndef LL_LLVFS_H
#define LL_LLVFS_H
#include <deque>
#include "lluuid.h"
#include "llassettype.h"
#include "llthread.h"
#include "llmutex.h"
enum EVFSValid
{
VFSVALID_UNKNOWN = 0,
VFSVALID_OK = 1,
VFSVALID_BAD_CORRUPT = 2,
VFSVALID_BAD_CANNOT_OPEN_READONLY = 3,
VFSVALID_BAD_CANNOT_CREATE = 4
};
// Lock types for open vfiles, pending async reads, and pending async appends
// (There are no async normal writes, currently)
enum EVFSLock
{
VFSLOCK_OPEN = 0,
VFSLOCK_READ = 1,
VFSLOCK_APPEND = 2,
VFSLOCK_COUNT = 3
};
// internal classes
class LLVFSBlock;
class LLVFSFileBlock;
class LLVFSFileSpecifier
{
public:
LLVFSFileSpecifier();
LLVFSFileSpecifier(const LLUUID &file_id, const LLAssetType::EType file_type);
bool operator<(const LLVFSFileSpecifier &rhs) const;
bool operator==(const LLVFSFileSpecifier &rhs) const;
public:
LLUUID mFileID;
LLAssetType::EType mFileType;
};
class LLVFS
{
private:
// Use createLLVFS() to open a VFS file
// Pass 0 to not presize
LLVFS(const std::string& index_filename,
const std::string& data_filename,
const BOOL read_only,
const U32 presize,
const BOOL remove_after_crash);
public:
~LLVFS();
// Use this function normally to create LLVFS files
// Pass 0 to not presize
static LLVFS * createLLVFS(const std::string& index_filename,
const std::string& data_filename,
const BOOL read_only,
const U32 presize,
const BOOL remove_after_crash);
BOOL isValid() const { return (VFSVALID_OK == mValid); }
EVFSValid getValidState() const { return mValid; }
// ---------- The following fucntions lock/unlock mDataMutex ----------
BOOL getExists(const LLUUID &file_id, const LLAssetType::EType file_type);
S32 getSize(const LLUUID &file_id, const LLAssetType::EType file_type);
BOOL checkAvailable(S32 max_size);
S32 getMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type);
BOOL setMaxSize(const LLUUID &file_id, const LLAssetType::EType file_type, S32 max_size);
void renameFile(const LLUUID &file_id, const LLAssetType::EType file_type,
const LLUUID &new_id, const LLAssetType::EType &new_type);
void removeFile(const LLUUID &file_id, const LLAssetType::EType file_type);
S32 getData(const LLUUID &file_id, const LLAssetType::EType file_type, U8 *buffer, S32 location, S32 length);
S32 storeData(const LLUUID &file_id, const LLAssetType::EType file_type, const U8 *buffer, S32 location, S32 length);
void incLock(const LLUUID &file_id, const LLAssetType::EType file_type, EVFSLock lock);
void decLock(const LLUUID &file_id, const LLAssetType::EType file_type, EVFSLock lock);
BOOL isLocked(const LLUUID &file_id, const LLAssetType::EType file_type, EVFSLock lock);
// ----------------------------------------------------------------
// Used to trigger evil WinXP behavior of "preloading" entire file into memory.
void pokeFiles();
// Verify that the index file contents match the in-memory file structure
// Very slow, do not call routinely. JC
void audit();
// Check for uninitialized blocks. Slow, do not call in release. JC
void checkMem();
// for debugging, prints a map of the vfs
void dumpMap();
void dumpLockCounts();
void dumpStatistics();
void listFiles();
void dumpFiles();
time_t creationTime();
protected:
void removeFileBlock(LLVFSFileBlock *fileblock);
void eraseBlockLength(LLVFSBlock *block);
void eraseBlock(LLVFSBlock *block);
void addFreeBlock(LLVFSBlock *block);
//void mergeFreeBlocks();
void useFreeSpace(LLVFSBlock *free_block, S32 length);
void sync(LLVFSFileBlock *block, BOOL remove = FALSE);
void presizeDataFile(const U32 size);
static LLFILE *openAndLock(const std::string& filename, const char* mode, BOOL read_lock);
static void unlockAndClose(FILE *fp);
// Can initiate LRU-based file removal to make space.
// The immune file block will not be removed.
LLVFSBlock *findFreeBlock(S32 size, LLVFSFileBlock *immune = NULL);
// lock/unlock data mutex (mDataMutex)
void lockData() { mDataMutex->lock(); }
void unlockData() { mDataMutex->unlock(); }
protected:
LLMutex* mDataMutex;
typedef std::map<LLVFSFileSpecifier, LLVFSFileBlock*> fileblock_map;
fileblock_map mFileBlocks;
typedef std::multimap<S32, LLVFSBlock*> blocks_length_map_t;
blocks_length_map_t mFreeBlocksByLength;
typedef std::multimap<U32, LLVFSBlock*> blocks_location_map_t;
blocks_location_map_t mFreeBlocksByLocation;
LLFILE *mDataFP;
LLFILE *mIndexFP;
std::deque<S32> mIndexHoles;
std::string mIndexFilename;
std::string mDataFilename;
BOOL mReadOnly;
EVFSValid mValid;
S32 mLockCounts[VFSLOCK_COUNT];
BOOL mRemoveAfterCrash;
};
extern LLVFS *gVFS;
#endif

View File

@ -1,300 +0,0 @@
/**
* @file llvfsthread.cpp
* @brief LLVFSThread implementation
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
#include "llvfsthread.h"
#include "llstl.h"
//============================================================================
/*static*/ std::string LLVFSThread::sDataPath = "";
/*static*/ LLVFSThread* LLVFSThread::sLocal = NULL;
//============================================================================
// Run on MAIN thread
//static
void LLVFSThread::initClass(bool local_is_threaded)
{
llassert(sLocal == NULL);
sLocal = new LLVFSThread(local_is_threaded);
}
//static
S32 LLVFSThread::updateClass(U32 ms_elapsed)
{
sLocal->update((F32)ms_elapsed);
return sLocal->getPending();
}
//static
void LLVFSThread::cleanupClass()
{
sLocal->setQuitting();
while (sLocal->getPending())
{
sLocal->update(0);
}
delete sLocal;
sLocal = 0;
}
//----------------------------------------------------------------------------
LLVFSThread::LLVFSThread(bool threaded) :
LLQueuedThread("VFS", threaded)
{
}
LLVFSThread::~LLVFSThread()
{
// ~LLQueuedThread() will be called here
}
//----------------------------------------------------------------------------
LLVFSThread::handle_t LLVFSThread::read(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes, U32 priority, U32 flags)
{
handle_t handle = generateHandle();
priority = llmax(priority, (U32)PRIORITY_LOW); // All reads are at least PRIORITY_LOW
Request* req = new Request(handle, priority, flags, FILE_READ, vfs, file_id, file_type,
buffer, offset, numbytes);
bool res = addRequest(req);
if (!res)
{
LL_ERRS() << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << LL_ENDL;
req->deleteRequest();
handle = nullHandle();
}
return handle;
}
S32 LLVFSThread::readImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes)
{
handle_t handle = generateHandle();
Request* req = new Request(handle, PRIORITY_IMMEDIATE, 0, FILE_READ, vfs, file_id, file_type,
buffer, offset, numbytes);
S32 res = addRequest(req) ? 1 : 0;
if (res == 0)
{
LL_ERRS() << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << LL_ENDL;
req->deleteRequest();
}
else
{
llverify(waitForResult(handle, false) == true);
res = req->getBytesRead();
completeRequest(handle);
}
return res;
}
LLVFSThread::handle_t LLVFSThread::write(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes, U32 flags)
{
handle_t handle = generateHandle();
Request* req = new Request(handle, 0, flags, FILE_WRITE, vfs, file_id, file_type,
buffer, offset, numbytes);
bool res = addRequest(req);
if (!res)
{
LL_ERRS() << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << LL_ENDL;
req->deleteRequest();
handle = nullHandle();
}
return handle;
}
S32 LLVFSThread::writeImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes)
{
handle_t handle = generateHandle();
Request* req = new Request(handle, PRIORITY_IMMEDIATE, 0, FILE_WRITE, vfs, file_id, file_type,
buffer, offset, numbytes);
S32 res = addRequest(req) ? 1 : 0;
if (res == 0)
{
LL_ERRS() << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << LL_ENDL;
req->deleteRequest();
}
else
{
llverify(waitForResult(handle, false) == true);
res = req->getBytesRead();
completeRequest(handle);
}
return res;
}
// LLVFSThread::handle_t LLVFSThread::rename(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
// const LLUUID &new_id, const LLAssetType::EType new_type, U32 flags)
// {
// handle_t handle = generateHandle();
// LLUUID* new_idp = new LLUUID(new_id); // deleted with Request
// // new_type is passed as "numbytes"
// Request* req = new Request(handle, 0, flags, FILE_RENAME, vfs, file_id, file_type,
// (U8*)new_idp, 0, (S32)new_type);
// bool res = addRequest(req);
// if (!res)
// {
// LL_ERRS() << "LLVFSThread::read called after LLVFSThread::cleanupClass()" << LL_ENDL;
// req->deleteRequest();
// handle = nullHandle();
// }
// return handle;
// }
//============================================================================
LLVFSThread::Request::Request(handle_t handle, U32 priority, U32 flags,
operation_t op, LLVFS* vfs,
const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes) :
QueuedRequest(handle, priority, flags),
mOperation(op),
mVFS(vfs),
mFileID(file_id),
mFileType(file_type),
mBuffer(buffer),
mOffset(offset),
mBytes(numbytes),
mBytesRead(0)
{
llassert(mBuffer);
if (numbytes <= 0 && mOperation != FILE_RENAME)
{
LL_WARNS() << "LLVFSThread: Request with numbytes = " << numbytes
<< " operation = " << op
<< " offset " << offset
<< " file_type " << file_type << LL_ENDL;
}
if (mOperation == FILE_WRITE)
{
S32 blocksize = mVFS->getMaxSize(mFileID, mFileType);
if (blocksize < 0)
{
LL_WARNS() << "VFS write to temporary block (shouldn't happen)" << LL_ENDL;
}
mVFS->incLock(mFileID, mFileType, VFSLOCK_APPEND);
}
else if (mOperation == FILE_RENAME)
{
mVFS->incLock(mFileID, mFileType, VFSLOCK_APPEND);
}
else // if (mOperation == FILE_READ)
{
mVFS->incLock(mFileID, mFileType, VFSLOCK_READ);
}
}
// dec locks as soon as a request finishes
void LLVFSThread::Request::finishRequest(bool completed)
{
if (mOperation == FILE_WRITE)
{
mVFS->decLock(mFileID, mFileType, VFSLOCK_APPEND);
}
else if (mOperation == FILE_RENAME)
{
mVFS->decLock(mFileID, mFileType, VFSLOCK_APPEND);
}
else // if (mOperation == FILE_READ)
{
mVFS->decLock(mFileID, mFileType, VFSLOCK_READ);
}
}
void LLVFSThread::Request::deleteRequest()
{
if (getStatus() == STATUS_QUEUED)
{
LL_ERRS() << "Attempt to delete a queued LLVFSThread::Request!" << LL_ENDL;
}
if (mOperation == FILE_WRITE)
{
if (mFlags & FLAG_AUTO_DELETE)
{
delete [] mBuffer;
}
}
else if (mOperation == FILE_RENAME)
{
LLUUID* new_idp = (LLUUID*)mBuffer;
delete new_idp;
}
LLQueuedThread::QueuedRequest::deleteRequest();
}
bool LLVFSThread::Request::processRequest()
{
bool complete = false;
if (mOperation == FILE_READ)
{
llassert(mOffset >= 0);
mBytesRead = mVFS->getData(mFileID, mFileType, mBuffer, mOffset, mBytes);
complete = true;
//LL_INFOS() << llformat("LLVFSThread::READ '%s': %d bytes arg:%d",getFilename(),mBytesRead) << LL_ENDL;
}
else if (mOperation == FILE_WRITE)
{
mBytesRead = mVFS->storeData(mFileID, mFileType, mBuffer, mOffset, mBytes);
complete = true;
//LL_INFOS() << llformat("LLVFSThread::WRITE '%s': %d bytes arg:%d",getFilename(),mBytesRead) << LL_ENDL;
}
else if (mOperation == FILE_RENAME)
{
LLUUID* new_idp = (LLUUID*)mBuffer;
LLAssetType::EType new_type = (LLAssetType::EType)mBytes;
mVFS->renameFile(mFileID, mFileType, *new_idp, new_type);
mFileID = *new_idp;
complete = true;
//LL_INFOS() << llformat("LLVFSThread::RENAME '%s': %d bytes arg:%d",getFilename(),mBytesRead) << LL_ENDL;
}
else
{
LL_ERRS() << llformat("LLVFSThread::unknown operation: %d", mOperation) << LL_ENDL;
}
return complete;
}
//============================================================================

View File

@ -1,140 +0,0 @@
/**
* @file llvfsthread.h
* @brief LLVFSThread definition
*
* $LicenseInfo:firstyear=2001&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$
*/
#ifndef LL_LLVFSTHREAD_H
#define LL_LLVFSTHREAD_H
#include <queue>
#include <string>
#include <map>
#include <set>
#include "llqueuedthread.h"
#include "llvfs.h"
//============================================================================
class LLVFSThread : public LLQueuedThread
{
//------------------------------------------------------------------------
public:
enum operation_t {
FILE_READ,
FILE_WRITE,
FILE_RENAME
};
//------------------------------------------------------------------------
public:
class Request : public QueuedRequest
{
protected:
~Request() {}; // use deleteRequest()
public:
Request(handle_t handle, U32 priority, U32 flags,
operation_t op, LLVFS* vfs,
const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes);
S32 getBytesRead()
{
return mBytesRead;
}
S32 getOperation()
{
return mOperation;
}
U8* getBuffer()
{
return mBuffer;
}
LLVFS* getVFS()
{
return mVFS;
}
std::string getFilename()
{
std::string tstring;
mFileID.toString(tstring);
return tstring;
}
/*virtual*/ bool processRequest();
/*virtual*/ void finishRequest(bool completed);
/*virtual*/ void deleteRequest();
private:
operation_t mOperation;
LLVFS* mVFS;
LLUUID mFileID;
LLAssetType::EType mFileType;
U8* mBuffer; // dest for reads, source for writes, new UUID for rename
S32 mOffset; // offset into file, -1 = append (WRITE only)
S32 mBytes; // bytes to read from file, -1 = all (new mFileType for rename)
S32 mBytesRead; // bytes read from file
};
//------------------------------------------------------------------------
public:
static std::string sDataPath;
static LLVFSThread* sLocal; // Default worker thread
public:
LLVFSThread(bool threaded = TRUE);
~LLVFSThread();
// Return a Request handle
handle_t read(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type, /* Flawfinder: ignore */
U8* buffer, S32 offset, S32 numbytes, U32 pri=PRIORITY_NORMAL, U32 flags = 0);
handle_t write(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes, U32 flags);
// SJB: rename seems to have issues, especially when threaded
// handle_t rename(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
// const LLUUID &new_id, const LLAssetType::EType new_type, U32 flags);
// Return number of bytes read
S32 readImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes);
S32 writeImmediate(LLVFS* vfs, const LLUUID &file_id, const LLAssetType::EType file_type,
U8* buffer, S32 offset, S32 numbytes);
/*virtual*/ bool processRequest(QueuedRequest* req);
public:
static void initClass(bool local_is_threaded = TRUE); // Setup sLocal
static S32 updateClass(U32 ms_elapsed);
static void cleanupClass(); // Delete sLocal
static void setDataPath(const std::string& path) { sDataPath = path; }
};
//============================================================================
#endif // LL_LLVFSTHREAD_H

View File

@ -16,7 +16,7 @@ include(LLCommon)
include(LLImage) include(LLImage)
include(LLMath) include(LLMath)
include(LLRender) include(LLRender)
include(LLVFS) include(LLFileSystem)
include(LLWindow) include(LLWindow)
include(LLXML) include(LLXML)
include(UI) include(UI)
@ -26,7 +26,7 @@ include_directories(
${LLIMAGE_INCLUDE_DIRS} ${LLIMAGE_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS}
) )
@ -72,7 +72,7 @@ if (LINUX)
${LLIMAGE_LIBRARIES} ${LLIMAGE_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLRENDER_LIBRARIES} ${LLRENDER_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLWINDOW_LIBRARIES} ${LLWINDOW_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
${UI_LIBRARIES} # for GTK ${UI_LIBRARIES} # for GTK
@ -95,7 +95,7 @@ if (LINUX)
${LLIMAGE_LIBRARIES} ${LLIMAGE_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLRENDER_HEADLESS_LIBRARIES} ${LLRENDER_HEADLESS_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLWINDOW_HEADLESS_LIBRARIES} ${LLWINDOW_HEADLESS_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
fontconfig # For FCInit and other FC* functions. fontconfig # For FCInit and other FC* functions.

View File

@ -5,13 +5,13 @@ project(llxml)
include(00-Common) include(00-Common)
include(LLCommon) include(LLCommon)
include(LLMath) include(LLMath)
include(LLVFS) include(LLFileSystem)
include(LLXML) include(LLXML)
include_directories( include_directories(
${LLCOMMON_INCLUDE_DIRS} ${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
) )
include_directories( include_directories(
${LLCOMMON_SYSTEM_INCLUDE_DIRS} ${LLCOMMON_SYSTEM_INCLUDE_DIRS}
@ -42,7 +42,7 @@ add_library (llxml ${llxml_SOURCE_FILES})
# Libraries on which this library depends, needed for Linux builds # Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level # Sort by high-level to low-level
target_link_libraries( llxml target_link_libraries( llxml
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${EXPAT_LIBRARIES} ${EXPAT_LIBRARIES}

View File

@ -62,7 +62,7 @@ private:
void onTooltipCallback(std::string text); void onTooltipCallback(std::string text);
void onLoadStartCallback(); void onLoadStartCallback();
void onRequestExitCallback(); void onRequestExitCallback();
void onLoadEndCallback(int httpStatusCode); void onLoadEndCallback(int httpStatusCode, std::string url);
void onLoadError(int status, const std::string error_text); void onLoadError(int status, const std::string error_text);
void onAddressChangeCallback(std::string url); void onAddressChangeCallback(std::string url);
void onOpenPopupCallback(std::string url, std::string target); void onOpenPopupCallback(std::string url, std::string target);
@ -89,6 +89,8 @@ private:
bool mDisableGPU; bool mDisableGPU;
bool mDisableNetworkService; bool mDisableNetworkService;
bool mUseMockKeyChain; bool mUseMockKeyChain;
bool mDisableWebSecurity;
bool mFileAccessFromFileUrls;
std::string mUserAgentSubtring; std::string mUserAgentSubtring;
std::string mAuthUsername; std::string mAuthUsername;
std::string mAuthPassword; std::string mAuthPassword;
@ -124,6 +126,8 @@ MediaPluginBase(host_send_func, host_user_data)
mDisableGPU = false; mDisableGPU = false;
mDisableNetworkService = true; mDisableNetworkService = true;
mUseMockKeyChain = true; mUseMockKeyChain = true;
mDisableWebSecurity = false;
mFileAccessFromFileUrls = false;
mUserAgentSubtring = ""; mUserAgentSubtring = "";
mAuthUsername = ""; mAuthUsername = "";
mAuthPassword = ""; mAuthPassword = "";
@ -257,13 +261,14 @@ void MediaPluginCEF::onRequestExitCallback()
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// //
void MediaPluginCEF::onLoadEndCallback(int httpStatusCode) void MediaPluginCEF::onLoadEndCallback(int httpStatusCode, std::string url)
{ {
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete"); LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "navigate_complete");
//message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed? //message.setValue("uri", event.getEventUri()); // not easily available here in CEF - needed?
message.setValueS32("result_code", httpStatusCode); message.setValueS32("result_code", httpStatusCode);
message.setValueBoolean("history_back_available", mCEFLib->canGoBack()); message.setValueBoolean("history_back_available", mCEFLib->canGoBack());
message.setValueBoolean("history_forward_available", mCEFLib->canGoForward()); message.setValueBoolean("history_forward_available", mCEFLib->canGoForward());
message.setValue("uri", url);
sendMessage(message); sendMessage(message);
} }
@ -352,14 +357,16 @@ const std::vector<std::string> MediaPluginCEF::onFileDialog(dullahan::EFileDialo
} }
else if (dialog_type == dullahan::FD_SAVE_FILE) else if (dialog_type == dullahan::FD_SAVE_FILE)
{ {
mPickedFiles.clear();
mAuthOK = false; mAuthOK = false;
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "file_download"); LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "file_download");
message.setValueBoolean("blocking_request", true);
message.setValue("filename", default_file); message.setValue("filename", default_file);
sendMessage(message); sendMessage(message);
return std::vector<std::string>(); return mPickedFiles;
} }
return std::vector<std::string>(); return std::vector<std::string>();
@ -520,7 +527,7 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
mCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1)); mCEFLib->setOnTitleChangeCallback(std::bind(&MediaPluginCEF::onTitleChangeCallback, this, std::placeholders::_1));
mCEFLib->setOnTooltipCallback(std::bind(&MediaPluginCEF::onTooltipCallback, this, std::placeholders::_1)); mCEFLib->setOnTooltipCallback(std::bind(&MediaPluginCEF::onTooltipCallback, this, std::placeholders::_1));
mCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this)); mCEFLib->setOnLoadStartCallback(std::bind(&MediaPluginCEF::onLoadStartCallback, this));
mCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1)); mCEFLib->setOnLoadEndCallback(std::bind(&MediaPluginCEF::onLoadEndCallback, this, std::placeholders::_1, std::placeholders::_2));
mCEFLib->setOnLoadErrorCallback(std::bind(&MediaPluginCEF::onLoadError, this, std::placeholders::_1, std::placeholders::_2)); mCEFLib->setOnLoadErrorCallback(std::bind(&MediaPluginCEF::onLoadError, this, std::placeholders::_1, std::placeholders::_2));
mCEFLib->setOnAddressChangeCallback(std::bind(&MediaPluginCEF::onAddressChangeCallback, this, std::placeholders::_1)); mCEFLib->setOnAddressChangeCallback(std::bind(&MediaPluginCEF::onAddressChangeCallback, this, std::placeholders::_1));
mCEFLib->setOnOpenPopupCallback(std::bind(&MediaPluginCEF::onOpenPopupCallback, this, std::placeholders::_1, std::placeholders::_2)); mCEFLib->setOnOpenPopupCallback(std::bind(&MediaPluginCEF::onOpenPopupCallback, this, std::placeholders::_1, std::placeholders::_2));
@ -559,6 +566,19 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
settings.disable_network_service = mDisableNetworkService; settings.disable_network_service = mDisableNetworkService;
settings.use_mock_keychain = mUseMockKeyChain; settings.use_mock_keychain = mUseMockKeyChain;
#endif #endif
// these were added to facilitate loading images directly into a local
// web page for the prototype 360 project in 2017 - something that is
// disallowed normally by the browser security model. Now the the source
// (cubemap) images are stores as JavaScript, we can avoid opening up
// this security hole (it was only set for the 360 floater but still
// a concern). Leaving them here, explicitly turn off vs removing
// entirely from this source file so that others are aware of them
// in the future.
settings.disable_web_security = false;
settings.file_access_from_file_urls = false;
settings.flash_enabled = mPluginsEnabled;
// This setting applies to all plugins, not just Flash // This setting applies to all plugins, not just Flash
// Regarding, SL-15559 PDF files do not load in CEF v91, // Regarding, SL-15559 PDF files do not load in CEF v91,
// it turns out that on Windows, PDF support is treated // it turns out that on Windows, PDF support is treated
@ -685,6 +705,11 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
std::string uri = message_in.getValue("uri"); std::string uri = message_in.getValue("uri");
mCEFLib->navigate(uri); mCEFLib->navigate(uri);
} }
else if (message_name == "execute_javascript")
{
std::string code = message_in.getValue("code");
mCEFLib->executeJavaScript(code);
}
else if (message_name == "set_cookie") else if (message_name == "set_cookie")
{ {
std::string uri = message_in.getValue("uri"); std::string uri = message_in.getValue("uri");
@ -880,6 +905,14 @@ void MediaPluginCEF::receiveMessage(const char* message_string)
{ {
mDisableGPU = message_in.getValueBoolean("disable"); mDisableGPU = message_in.getValueBoolean("disable");
} }
else if (message_name == "web_security_disabled")
{
mDisableWebSecurity = message_in.getValueBoolean("disabled");
}
else if (message_name == "file_access_from_file_urls")
{
mFileAccessFromFileUrls = message_in.getValueBoolean("enabled");
}
} }
else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME) else if (message_class == LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME)
{ {

View File

@ -12,11 +12,13 @@ include(bugsplat)
include(BuildPackagesInfo) include(BuildPackagesInfo)
include(BuildVersion) include(BuildVersion)
include(CMakeCopyIfDifferent) include(CMakeCopyIfDifferent)
include(CubemapToEquirectangularJS)
include(DBusGlib) include(DBusGlib)
include(DragDrop) include(DragDrop)
include(EXPAT) include(EXPAT)
include(FMODSTUDIO) include(FMODSTUDIO)
include(Hunspell) include(Hunspell)
include(JPEGEncoderBasic)
include(JsonCpp) include(JsonCpp)
include(LLAppearance) include(LLAppearance)
include(LLAudio) include(LLAudio)
@ -37,7 +39,7 @@ include(LLPlugin)
include(LLPrimitive) include(LLPrimitive)
include(LLRender) include(LLRender)
include(LLUI) include(LLUI)
include(LLVFS) include(LLFileSystem)
include(LLWindow) include(LLWindow)
include(LLXML) include(LLXML)
include(NDOF) include(NDOF)
@ -47,6 +49,7 @@ include(OpenGL)
include(OpenSSL) include(OpenSSL)
include(PNG) include(PNG)
include(TemplateCheck) include(TemplateCheck)
include(ThreeJS)
include(Tracy) include(Tracy)
include(UI) include(UI)
include(UnixInstall) include(UnixInstall)
@ -83,7 +86,7 @@ include_directories(
${LLPRIMITIVE_INCLUDE_DIRS} ${LLPRIMITIVE_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS} ${LLRENDER_INCLUDE_DIRS}
${LLUI_INCLUDE_DIRS} ${LLUI_INCLUDE_DIRS}
${LLVFS_INCLUDE_DIRS} ${LLFILESYSTEM_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS} ${LLWINDOW_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS}
${LLLOGIN_INCLUDE_DIRS} ${LLLOGIN_INCLUDE_DIRS}
@ -207,6 +210,7 @@ set(viewer_SOURCE_FILES
llfilteredwearablelist.cpp llfilteredwearablelist.cpp
llfirstuse.cpp llfirstuse.cpp
llflexibleobject.cpp llflexibleobject.cpp
llfloater360capture.cpp
llfloaterabout.cpp llfloaterabout.cpp
llfloaterbvhpreview.cpp llfloaterbvhpreview.cpp
llfloateraddpaymentmethod.cpp llfloateraddpaymentmethod.cpp
@ -842,6 +846,7 @@ set(viewer_HEADER_FILES
llfilteredwearablelist.h llfilteredwearablelist.h
llfirstuse.h llfirstuse.h
llflexibleobject.h llflexibleobject.h
llfloater360capture.h
llfloaterabout.h llfloaterabout.h
llfloaterbvhpreview.h llfloaterbvhpreview.h
llfloateraddpaymentmethod.h llfloateraddpaymentmethod.h
@ -2027,7 +2032,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${LLRENDER_LIBRARIES} ${LLRENDER_LIBRARIES}
${FREETYPE_LIBRARIES} ${FREETYPE_LIBRARIES}
${LLUI_LIBRARIES} ${LLUI_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLWINDOW_LIBRARIES} ${LLWINDOW_LIBRARIES}
${LLXML_LIBRARIES} ${LLXML_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
@ -2450,7 +2455,7 @@ if (LL_TESTS)
set(test_libs set(test_libs
${LLMESSAGE_LIBRARIES} ${LLMESSAGE_LIBRARIES}
${WINDOWS_LIBRARIES} ${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${GOOGLEMOCK_LIBRARIES} ${GOOGLEMOCK_LIBRARIES}
@ -2465,7 +2470,7 @@ if (LL_TESTS)
set(test_libs set(test_libs
${WINDOWS_LIBRARIES} ${WINDOWS_LIBRARIES}
${LLVFS_LIBRARIES} ${LLFILESYSTEM_LIBRARIES}
${LLMATH_LIBRARIES} ${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES} ${LLCOMMON_LIBRARIES}
${LLMESSAGE_LIBRARIES} ${LLMESSAGE_LIBRARIES}

View File

@ -1 +1 @@
6.5.1 6.5.2

View File

@ -276,4 +276,15 @@
is_running_function="Floater.IsOpen" is_running_function="Floater.IsOpen"
is_running_parameters="my_environments" is_running_parameters="my_environments"
/> />
<command name="360capture"
available_in_toybox="true"
is_flashing_allowed="true"
icon="Command_360_Capture_Icon"
label_ref="Command_360_Capture_Label"
tooltip_ref="Command_360_Capture_Tooltip"
execute_function="Floater.ToggleOrBringToFront"
execute_parameters="360capture"
is_running_function="Floater.IsOpen"
is_running_parameters="360capture"
/>
</commands> </commands>

View File

@ -1351,6 +1351,39 @@
<key>Value</key> <key>Value</key>
<integer>23</integer> <integer>23</integer>
</map> </map>
<key>EnableDiskCacheDebugInfo</key>
<map>
<key>Comment</key>
<string>When set, display additional cache debugging information</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DiskCachePercentOfTotal</key>
<map>
<key>Comment</key>
<string>The percent of total cache size (defined by CacheSize) to use for the disk cache</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>20.0</real>
</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>cache</string>
</map>
<key>CacheLocation</key> <key>CacheLocation</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -2066,6 +2099,28 @@
<key>Value</key> <key>Value</key>
<integer>1</integer> <integer>1</integer>
</map> </map>
<key>BrowserFileAccessFromFileUrls</key>
<map>
<key>Comment</key>
<string>Allow access to local files via file urls in the embedded browser</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>BrowserPluginsEnabled</key>
<map>
<key>Comment</key>
<string>Enable Web plugins in the built-in Web browser?</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>ChatBarCustomWidth</key> <key>ChatBarCustomWidth</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -2815,17 +2870,6 @@
<key>Value</key> <key>Value</key>
<integer>-1</integer> <integer>-1</integer>
</map> </map>
<key>DebugStatModeVFSPendingOps</key>
<map>
<key>Comment</key>
<string>Mode of stat in Statistics floater</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
<integer>-1</integer>
</map>
<key>DebugStatModeTimeDialation</key> <key>DebugStatModeTimeDialation</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -3618,17 +3662,6 @@
<key>Value</key> <key>Value</key>
<integer>4</integer> <integer>4</integer>
</map> </map>
<key>DumpVFSCaches</key>
<map>
<key>Comment</key>
<string>Dump VFS caches on startup.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>DynamicCameraStrength</key> <key>DynamicCameraStrength</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -14134,7 +14167,7 @@
<key>Value</key> <key>Value</key>
<integer>1</integer> <integer>1</integer>
</map> </map>
<key>RenderDelayVBUpdate</key> <key>RenderDelayVBUpdate</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Delay vertex buffer updates until just before rendering</string> <string>Delay vertex buffer updates until just before rendering</string>
@ -14277,28 +14310,6 @@
<key>Value</key> <key>Value</key>
<string/> <string/>
</map> </map>
<key>VFSOldSize</key>
<map>
<key>Comment</key>
<string>[DO NOT MODIFY] Controls resizing of local file cache</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>VFSSalt</key>
<map>
<key>Comment</key>
<string>[DO NOT MODIFY] Controls local file caching behavior</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>VelocityInterpolate</key> <key>VelocityInterpolate</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
@ -16675,18 +16686,104 @@
<key>Value</key> <key>Value</key>
<integer>1</integer> <integer>1</integer>
</map> </map>
<key>UpdateAppWindowTitleBar</key> <key>360CaptureUseInterestListCap</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Updates the application window title bar with brief information about user/location</string> <string>Flag if set, uses the new InterestList cap to ask the simulator for full content</string>
<key>Persist</key> <key>Persist</key>
<integer>1</integer> <integer>1</integer>
<key>Type</key> <key>Type</key>
<string>Boolean</string> <string>Boolean</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>1</integer>
</map>
<key>360CaptureJPEGEncodeQuality</key>
<map>
<key>Comment</key>
<string>Quality value to use in the JPEG encoder (0..100)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>95</integer>
</map>
<key>360CaptureDebugSaveImage</key>
<map>
<key>Comment</key>
<string>Flag if set, saves off each cube map as an image, as well as the JavaScript data URL, for debugging purposes</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
<key>360CaptureOutputImageWidth</key>
<map>
<key>Comment</key>
<string>Width of the output 360 equirectangular image</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>4096</integer>
</map>
<key>360CaptureHideAvatars</key>
<map>
<key>Comment</key>
<string>Flag if set, removes all the avatars from the 360 snapshot</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map> </map>
<key>360CaptureCameraFOV</key>
<map>
<key>Comment</key>
<string>Field of view of the WebGL camera that converts the cubemap to an equirectangular image</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>75</integer>
</map>
<key>360CaptureNumRenderPasses</key>
<map>
<key>Comment</key>
<string>Number of times to render the scene while taking a snapshot</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>U32</string>
<key>Value</key>
<integer>3</integer>
</map>
<key>ResetUIScaleOnFirstRun</key>
<map>
<key>Comment</key>
<string>Resets the UI scale factor on first run due to changed display scaling behavior</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>1</integer>
</map>
<key>UpdateAppWindowTitleBar</key>
<map>
<key>Comment</key>
<string>Updates the application window title bar with brief information about user/location</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
<integer>0</integer>
</map>
</map> </map>
</llsd> </llsd>

View File

@ -2895,7 +2895,7 @@ bool LLAgent::requestGetCapability(const std::string &capName, httpCallback_t cb
{ {
std::string url; std::string url;
url = getRegion()->getCapability(capName); url = getRegionCapability(capName);
if (url.empty()) if (url.empty())
{ {
@ -4636,23 +4636,19 @@ void LLAgent::requestAgentUserInfoCoro(std::string capurl)
return; return;
} }
bool im_via_email;
bool is_verified_email;
std::string email; std::string email;
std::string dir_visibility; std::string dir_visibility;
im_via_email = result["im_via_email"].asBoolean();
is_verified_email = result["is_verified"].asBoolean();
email = result["email"].asString(); email = result["email"].asString();
dir_visibility = result["directory_visibility"].asString(); dir_visibility = result["directory_visibility"].asString();
// TODO: This should probably be changed. I'm not entirely comfortable // TODO: This should probably be changed. I'm not entirely comfortable
// having LLAgent interact directly with the UI in this way. // having LLAgent interact directly with the UI in this way.
LLFloaterPreference::updateUserInfo(dir_visibility, im_via_email, is_verified_email); LLFloaterPreference::updateUserInfo(dir_visibility);
LLFloaterSnapshot::setAgentEmail(email); LLFloaterSnapshot::setAgentEmail(email);
} }
void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility) void LLAgent::sendAgentUpdateUserInfo(const std::string& directory_visibility)
{ {
std::string cap; std::string cap;
@ -4665,16 +4661,16 @@ void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& dire
if (!cap.empty()) if (!cap.empty())
{ {
LLCoros::instance().launch("updateAgentUserInfoCoro", LLCoros::instance().launch("updateAgentUserInfoCoro",
boost::bind(&LLAgent::updateAgentUserInfoCoro, this, cap, im_via_email, directory_visibility)); boost::bind(&LLAgent::updateAgentUserInfoCoro, this, cap, directory_visibility));
} }
else else
{ {
sendAgentUpdateUserInfoMessage(im_via_email, directory_visibility); sendAgentUpdateUserInfoMessage(directory_visibility);
} }
} }
void LLAgent::updateAgentUserInfoCoro(std::string capurl, bool im_via_email, std::string directory_visibility) void LLAgent::updateAgentUserInfoCoro(std::string capurl, std::string directory_visibility)
{ {
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
@ -4685,8 +4681,8 @@ void LLAgent::updateAgentUserInfoCoro(std::string capurl, bool im_via_email, std
httpOpts->setFollowRedirects(true); httpOpts->setFollowRedirects(true);
LLSD body(LLSDMap LLSD body(LLSDMap
("dir_visibility", LLSD::String(directory_visibility)) ("dir_visibility", LLSD::String(directory_visibility)));
("im_via_email", LLSD::Boolean(im_via_email)));
LLSD result = httpAdapter->postAndSuspend(httpRequest, capurl, body, httpOpts, httpHeaders); LLSD result = httpAdapter->postAndSuspend(httpRequest, capurl, body, httpOpts, httpHeaders);
@ -4714,14 +4710,13 @@ void LLAgent::sendAgentUserInfoRequestMessage()
sendReliableMessage(); sendReliableMessage();
} }
void LLAgent::sendAgentUpdateUserInfoMessage(bool im_via_email, const std::string& directory_visibility) void LLAgent::sendAgentUpdateUserInfoMessage(const std::string& directory_visibility)
{ {
gMessageSystem->newMessageFast(_PREHASH_UpdateUserInfo); gMessageSystem->newMessageFast(_PREHASH_UpdateUserInfo);
gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->nextBlockFast(_PREHASH_AgentData);
gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID());
gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID());
gMessageSystem->nextBlockFast(_PREHASH_UserData); gMessageSystem->nextBlockFast(_PREHASH_UserData);
gMessageSystem->addBOOLFast(_PREHASH_IMViaEMail, im_via_email);
gMessageSystem->addString("DirectoryVisibility", directory_visibility); gMessageSystem->addString("DirectoryVisibility", directory_visibility);
gAgent.sendReliableMessage(); gAgent.sendReliableMessage();

View File

@ -928,14 +928,14 @@ public:
void sendAgentUserInfoRequest(); void sendAgentUserInfoRequest();
// IM to Email and Online visibility // IM to Email and Online visibility
void sendAgentUpdateUserInfo(bool im_to_email, const std::string& directory_visibility); void sendAgentUpdateUserInfo(const std::string& directory_visibility);
private: private:
void requestAgentUserInfoCoro(std::string capurl); void requestAgentUserInfoCoro(std::string capurl);
void updateAgentUserInfoCoro(std::string capurl, bool im_via_email, std::string directory_visibility); void updateAgentUserInfoCoro(std::string capurl, std::string directory_visibility);
// DEPRECATED: may be removed when User Info cap propagates // DEPRECATED: may be removed when User Info cap propagates
void sendAgentUserInfoRequestMessage(); void sendAgentUserInfoRequestMessage();
void sendAgentUpdateUserInfoMessage(bool im_via_email, const std::string& directory_visibility); void sendAgentUpdateUserInfoMessage(const std::string& directory_visibility);
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Receive // Receive

View File

@ -100,6 +100,7 @@
#include "lllogininstance.h" #include "lllogininstance.h"
#include "llprogressview.h" #include "llprogressview.h"
#include "llvocache.h" #include "llvocache.h"
#include "lldiskcache.h"
#include "llvopartgroup.h" #include "llvopartgroup.h"
#include "llweb.h" #include "llweb.h"
#include "llfloatertexturefetchdebugger.h" #include "llfloatertexturefetchdebugger.h"
@ -117,8 +118,6 @@
#include "llprimitive.h" #include "llprimitive.h"
#include "llurlaction.h" #include "llurlaction.h"
#include "llurlentry.h" #include "llurlentry.h"
#include "llvfile.h"
#include "llvfsthread.h"
#include "llvolumemgr.h" #include "llvolumemgr.h"
#include "llxfermanager.h" #include "llxfermanager.h"
#include "llphysicsextensions.h" #include "llphysicsextensions.h"
@ -343,9 +342,6 @@ bool gUseWireframe = FALSE;
//use for remember deferred mode in wireframe switch //use for remember deferred mode in wireframe switch
bool gInitialDeferredModeForWireframe = FALSE; bool gInitialDeferredModeForWireframe = FALSE;
// VFS globals - see llappviewer.h
LLVFS* gStaticVFS = NULL;
LLMemoryInfo gSysMemory; LLMemoryInfo gSysMemory;
U64Bytes gMemoryAllocated(0); // updated in display_stats() in llviewerdisplay.cpp U64Bytes gMemoryAllocated(0); // updated in display_stats() in llviewerdisplay.cpp
@ -402,12 +398,6 @@ void init_default_trans_args()
default_trans_args.insert("create_account_url"); 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> struct SettingsFile : public LLInitParam::Block<SettingsFile>
{ {
Mandatory<std::string> name; Mandatory<std::string> name;
@ -576,7 +566,6 @@ static void settings_to_globals()
static void settings_modify() static void settings_modify()
{ {
LLRenderTarget::sUseFBO = gSavedSettings.getBOOL("RenderDeferred");
LLPipeline::sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater"); LLPipeline::sRenderTransparentWater = gSavedSettings.getBOOL("RenderTransparentWater");
LLPipeline::sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); LLPipeline::sRenderBump = gSavedSettings.getBOOL("RenderObjectBump");
LLPipeline::sRenderDeferred = LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred"); LLPipeline::sRenderDeferred = LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred");
@ -635,6 +624,7 @@ LLAppViewer* LLAppViewer::sInstance = NULL;
LLTextureCache* LLAppViewer::sTextureCache = NULL; LLTextureCache* LLAppViewer::sTextureCache = NULL;
LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL; LLImageDecodeThread* LLAppViewer::sImageDecodeThread = NULL;
LLTextureFetch* LLAppViewer::sTextureFetch = NULL; LLTextureFetch* LLAppViewer::sTextureFetch = NULL;
LLPurgeDiskCacheThread* LLAppViewer::sPurgeDiskCacheThread = NULL;
std::string getRuntime() std::string getRuntime()
{ {
@ -928,10 +918,6 @@ bool LLAppViewer::init()
// *Note: this is where gViewerStats used to be created. // *Note: this is where gViewerStats used to be created.
//
// Initialize the VFS, and gracefully handle initialization errors
//
if (!initCache()) if (!initCache())
{ {
LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL; LL_WARNS("InitInfo") << "Failed to init cache" << LL_ENDL;
@ -1069,26 +1055,26 @@ bool LLAppViewer::init()
|| mNumSessions % 20 == 0 //periodically remind user to update driver || mNumSessions % 20 == 0 //periodically remind user to update driver
) )
{ {
LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedIntelDriver"); LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedIntelDriver");
std::string gpu_name = ll_safe_string((const char *)glGetString(GL_RENDERER)); std::string gpu_name = ll_safe_string((const char *)glGetString(GL_RENDERER));
LL_INFOS("AppInit") << "Notifying user about obsolete intel driver for " << gpu_name << LL_ENDL; LL_INFOS("AppInit") << "Notifying user about obsolete intel driver for " << gpu_name << LL_ENDL;
details.setArg("[VERSION]", driver); details.setArg("[VERSION]", driver);
details.setArg("[GPUNAME]", gpu_name); details.setArg("[GPUNAME]", gpu_name);
S32 button = OSMessageBox(details.getString(), S32 button = OSMessageBox(details.getString(),
LLStringUtil::null, LLStringUtil::null,
OSMB_YESNO); OSMB_YESNO);
if (OSBTN_YES == button && gViewerWindow) if (OSBTN_YES == button && gViewerWindow)
{
std::string url = LLWeb::escapeURL(LLTrans::getString("IntelDriverPage"));
if (gViewerWindow->getWindow())
{ {
gViewerWindow->getWindow()->spawnWebBrowser(url, false); std::string url = LLWeb::escapeURL(LLTrans::getString("IntelDriverPage"));
if (gViewerWindow->getWindow())
{
gViewerWindow->getWindow()->spawnWebBrowser(url, false);
}
} }
} }
} }
} }
} }
}
#endif #endif
// Obsolete? mExpectedGLVersion is always zero // Obsolete? mExpectedGLVersion is always zero
@ -1339,7 +1325,6 @@ static LLTrace::BlockTimerStatHandle FTM_TEXTURE_CACHE("Texture Cache");
static LLTrace::BlockTimerStatHandle FTM_DECODE("Image Decode"); static LLTrace::BlockTimerStatHandle FTM_DECODE("Image Decode");
static LLTrace::BlockTimerStatHandle FTM_FETCH("Image Fetch"); 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_LFS("LFS Thread");
static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads"); static LLTrace::BlockTimerStatHandle FTM_PAUSE_THREADS("Pause Threads");
static LLTrace::BlockTimerStatHandle FTM_IDLE("Idle"); static LLTrace::BlockTimerStatHandle FTM_IDLE("Idle");
@ -1610,10 +1595,6 @@ bool LLAppViewer::doFrame()
work_pending += updateTextureThreads(max_time); work_pending += updateTextureThreads(max_time);
{
LL_RECORD_BLOCK_TIME(FTM_VFS);
io_pending += LLVFSThread::updateClass(1);
}
{ {
LL_RECORD_BLOCK_TIME(FTM_LFS); LL_RECORD_BLOCK_TIME(FTM_LFS);
io_pending += LLLFSThread::updateClass(1); io_pending += LLLFSThread::updateClass(1);
@ -1621,7 +1602,7 @@ bool LLAppViewer::doFrame()
if (io_pending > 1000) if (io_pending > 1000)
{ {
ms_sleep(llmin(io_pending/100,100)); // give the vfs some time to catch up ms_sleep(llmin(io_pending/100,100)); // give the lfs some time to catch up
} }
total_work_pending += work_pending ; total_work_pending += work_pending ;
@ -1644,7 +1625,6 @@ bool LLAppViewer::doFrame()
if(!total_io_pending) //pause file threads if nothing to process. if(!total_io_pending) //pause file threads if nothing to process.
{ {
LL_PROFILE_ZONE_NAMED( "df LLVFSThread" ) LL_PROFILE_ZONE_NAMED( "df LLVFSThread" )
LLVFSThread::sLocal->pause();
LLLFSThread::sLocal->pause(); LLLFSThread::sLocal->pause();
} }
@ -1712,12 +1692,11 @@ S32 LLAppViewer::updateTextureThreads(F32 max_time)
return work_pending; return work_pending;
} }
void LLAppViewer::flushVFSIO() void LLAppViewer::flushLFSIO()
{ {
while (1) while (1)
{ {
S32 pending = LLVFSThread::updateClass(0); S32 pending = LLLFSThread::updateClass(0);
pending += LLLFSThread::updateClass(0);
if (!pending) if (!pending)
{ {
break; break;
@ -1734,12 +1713,12 @@ bool LLAppViewer::cleanup()
// we're about to destroy below. Run them first. // we're about to destroy below. Run them first.
mOnCleanup(); mOnCleanup();
LLAtmosphere::cleanupClass(); LLAtmosphere::cleanupClass();
//ditch LLVOAvatarSelf instance //ditch LLVOAvatarSelf instance
gAgentAvatarp = NULL; gAgentAvatarp = NULL;
LLNotifications::instance().clear(); LLNotifications::instance().clear();
// workaround for DEV-35406 crash on shutdown // workaround for DEV-35406 crash on shutdown
LLEventPumps::instance().reset(); LLEventPumps::instance().reset();
@ -1776,14 +1755,14 @@ bool LLAppViewer::cleanup()
// to ensure shutdown order // to ensure shutdown order
LLMortician::setZealous(TRUE); LLMortician::setZealous(TRUE);
// Give any remaining SLPlugin instances a chance to exit cleanly. // Give any remaining SLPlugin instances a chance to exit cleanly.
LLPluginProcessParent::shutdown(); LLPluginProcessParent::shutdown();
disconnectViewer(); disconnectViewer();
LLViewerCamera::deleteSingleton(); LLViewerCamera::deleteSingleton();
LL_INFOS() << "Viewer disconnected" << LL_ENDL; LL_INFOS() << "Viewer disconnected" << LL_ENDL;
if (gKeyboard) if (gKeyboard)
{ {
gKeyboard->resetKeys(); gKeyboard->resetKeys();
@ -1815,7 +1794,7 @@ bool LLAppViewer::cleanup()
LLKeyframeDataCache::clear(); LLKeyframeDataCache::clear();
// End TransferManager before deleting systems it depends on (Audio, VFS, AssetStorage) // End TransferManager before deleting systems it depends on (Audio, AssetStorage)
#if 0 // this seems to get us stuck in an infinite loop... #if 0 // this seems to get us stuck in an infinite loop...
gTransferManager.cleanup(); gTransferManager.cleanup();
#endif #endif
@ -1848,15 +1827,15 @@ bool LLAppViewer::cleanup()
if (gAudiop) if (gAudiop)
{ {
// be sure to stop the internet stream cleanly BEFORE destroying the interface to stop it. // be sure to stop the internet stream cleanly BEFORE destroying the interface to stop it.
gAudiop->stopInternetStream(); gAudiop->stopInternetStream();
// shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem. // shut down the streaming audio sub-subsystem first, in case it relies on not outliving the general audio subsystem.
LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl(); LLStreamingAudioInterface *sai = gAudiop->getStreamingAudioImpl();
delete sai; delete sai;
gAudiop->setStreamingAudioImpl(NULL); gAudiop->setStreamingAudioImpl(NULL);
// shut down the audio subsystem // shut down the audio subsystem
gAudiop->shutdown(); gAudiop->shutdown();
delete gAudiop; delete gAudiop;
gAudiop = NULL; gAudiop = NULL;
@ -1882,8 +1861,8 @@ bool LLAppViewer::cleanup()
LL_INFOS() << "Cache files removed" << LL_ENDL; LL_INFOS() << "Cache files removed" << LL_ENDL;
// Wait for any pending VFS IO // Wait for any pending LFS IO
flushVFSIO(); flushLFSIO();
LL_INFOS() << "Shutting down Views" << LL_ENDL; LL_INFOS() << "Shutting down Views" << LL_ENDL;
// Destroy the UI // Destroy the UI
@ -1925,11 +1904,11 @@ bool LLAppViewer::cleanup()
delete gKeyboard; delete gKeyboard;
gKeyboard = NULL; gKeyboard = NULL;
if (LLViewerJoystick::instanceExists()) if (LLViewerJoystick::instanceExists())
{ {
// Turn off Space Navigator and similar devices // Turn off Space Navigator and similar devices
LLViewerJoystick::getInstance()->terminate(); LLViewerJoystick::getInstance()->terminate();
} }
LL_INFOS() << "Cleaning up Objects" << LL_ENDL; LL_INFOS() << "Cleaning up Objects" << LL_ENDL;
@ -1967,25 +1946,16 @@ bool LLAppViewer::cleanup()
SUBSYSTEM_CLEANUP(LLWorldMapView); SUBSYSTEM_CLEANUP(LLWorldMapView);
SUBSYSTEM_CLEANUP(LLFolderViewItem); 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; LL_INFOS() << "Saving Data" << LL_ENDL;
// Store the time of our current logoff // Store the time of our current logoff
gSavedPerAccountSettings.setU32("LastLogoff", time_corrected()); gSavedPerAccountSettings.setU32("LastLogoff", time_corrected());
if (LLEnvironment::instanceExists()) if (LLEnvironment::instanceExists())
{ {
//Store environment settings if necessary //Store environment settings if necessary
LLEnvironment::getInstance()->saveToSettings(); LLEnvironment::getInstance()->saveToSettings();
} }
// Must do this after all panels have been deleted because panels that have persistent rects // Must do this after all panels have been deleted because panels that have persistent rects
// save their rects on delete. // save their rects on delete.
@ -2035,7 +2005,7 @@ bool LLAppViewer::cleanup()
LLConversationLog::instance().cache(); LLConversationLog::instance().cache();
} }
clearSecHandler(); clearSecHandler();
if (mPurgeCacheOnExit) if (mPurgeCacheOnExit)
{ {
@ -2064,7 +2034,6 @@ bool LLAppViewer::cleanup()
pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread pending += LLAppViewer::getTextureCache()->update(1); // unpauses the worker thread
pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread pending += LLAppViewer::getImageDecodeThread()->update(1); // unpauses the image thread
pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread pending += LLAppViewer::getTextureFetch()->update(1); // unpauses the texture fetch thread
pending += LLVFSThread::updateClass(0);
pending += LLLFSThread::updateClass(0); pending += LLLFSThread::updateClass(0);
F64 idle_time = idleTimer.getElapsedTimeF64(); F64 idle_time = idleTimer.getElapsedTimeF64();
if(!pending) if(!pending)
@ -2078,13 +2047,13 @@ bool LLAppViewer::cleanup()
} }
} }
if (mPurgeUserDataOnExit) if (mPurgeUserDataOnExit)
{ {
// Ideally we should not save anything from this session since it is going to be purged now, // Ideally we should not save anything from this session since it is going to be purged now,
// but this is a very 'rare' case (user deleting himself), not worth overcomplicating 'save&cleanup' code // but this is a very 'rare' case (user deleting himself), not worth overcomplicating 'save&cleanup' code
std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + LLStartUp::getUserId(); std::string user_path = gDirUtilp->getOSUserAppDir() + gDirUtilp->getDirDelimiter() + LLStartUp::getUserId();
gDirUtilp->deleteDirAndContents(user_path); gDirUtilp->deleteDirAndContents(user_path);
} }
// Delete workers first // Delete workers first
// shotdown all worker threads before deleting them in case of co-dependencies // shotdown all worker threads before deleting them in case of co-dependencies
@ -2092,6 +2061,7 @@ bool LLAppViewer::cleanup()
sTextureFetch->shutdown(); sTextureFetch->shutdown();
sTextureCache->shutdown(); sTextureCache->shutdown();
sImageDecodeThread->shutdown(); sImageDecodeThread->shutdown();
sPurgeDiskCacheThread->shutdown();
sTextureFetch->shutDownTextureCacheThread() ; sTextureFetch->shutDownTextureCacheThread() ;
sTextureFetch->shutDownImageDecodeThread() ; sTextureFetch->shutDownImageDecodeThread() ;
@ -2107,13 +2077,15 @@ bool LLAppViewer::cleanup()
//MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl) //MUST happen AFTER SUBSYSTEM_CLEANUP(LLCurl)
delete sTextureCache; delete sTextureCache;
sTextureCache = NULL; sTextureCache = NULL;
delete sTextureFetch; delete sTextureFetch;
sTextureFetch = NULL; sTextureFetch = NULL;
delete sImageDecodeThread; delete sImageDecodeThread;
sImageDecodeThread = NULL; sImageDecodeThread = NULL;
delete mFastTimerLogThread; delete mFastTimerLogThread;
mFastTimerLogThread = NULL; mFastTimerLogThread = NULL;
delete sPurgeDiskCacheThread;
sPurgeDiskCacheThread = NULL;
if (LLFastTimerView::sAnalyzePerformance) if (LLFastTimerView::sAnalyzePerformance)
{ {
@ -2139,28 +2111,11 @@ bool LLAppViewer::cleanup()
gTextureList.shutdown(); // shutdown again in case a callback added something gTextureList.shutdown(); // shutdown again in case a callback added something
LLUIImageList::getInstance()->cleanUp(); LLUIImageList::getInstance()->cleanUp();
// This should eventually be done in LLAppViewer
SUBSYSTEM_CLEANUP(LLImage); SUBSYSTEM_CLEANUP(LLImage);
SUBSYSTEM_CLEANUP(LLVFSThread);
SUBSYSTEM_CLEANUP(LLLFSThread); 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; 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(); gSavedSettings.cleanup();
LLUIColorTable::instance().clear(); LLUIColorTable::instance().clear();
@ -2187,7 +2142,7 @@ bool LLAppViewer::cleanup()
// make sure nothing uses applyProxySettings by this point. // make sure nothing uses applyProxySettings by this point.
LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL; LL_INFOS() << "Cleaning up LLProxy." << LL_ENDL;
SUBSYSTEM_CLEANUP(LLProxy); SUBSYSTEM_CLEANUP(LLProxy);
LLCore::LLHttp::cleanup(); LLCore::LLHttp::cleanup();
ll_close_fail_log(); ll_close_fail_log();
@ -2208,7 +2163,7 @@ bool LLAppViewer::cleanup()
// deleteSingleton() methods. // deleteSingleton() methods.
LLSingletonBase::deleteAll(); LLSingletonBase::deleteAll();
LL_INFOS() << "Goodbye!" << LL_ENDL; LL_INFOS() << "Goodbye!" << LL_ENDL;
removeDumpDir(); removeDumpDir();
@ -2222,7 +2177,6 @@ bool LLAppViewer::initThreads()
LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange")); LLImage::initClass(gSavedSettings.getBOOL("TextureNewByteRange"),gSavedSettings.getS32("TextureReverseByteRange"));
LLVFSThread::initClass(enable_threads && false);
LLLFSThread::initClass(enable_threads && false); LLLFSThread::initClass(enable_threads && false);
// Image decoding // Image decoding
@ -2232,6 +2186,7 @@ bool LLAppViewer::initThreads()
sImageDecodeThread, sImageDecodeThread,
enable_threads && true, enable_threads && true,
app_metrics_qa_mode); app_metrics_qa_mode);
LLAppViewer::sPurgeDiskCacheThread = new LLPurgeDiskCacheThread();
if (LLTrace::BlockTimer::sLog || LLTrace::BlockTimer::sMetricLog) if (LLTrace::BlockTimer::sLog || LLTrace::BlockTimer::sMetricLog)
{ {
@ -2271,14 +2226,14 @@ void errorCallback(LLError::ELevel level, const std::string &error_string)
void LLAppViewer::initLoggingAndGetLastDuration() void LLAppViewer::initLoggingAndGetLastDuration()
{ {
// //
// Set up logging defaults for the viewer // Set up logging defaults for the viewer
// //
LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "") LLError::initForApplication( gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "")
,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "") ,gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "")
); );
LLError::addGenericRecorder(&errorCallback); LLError::addGenericRecorder(&errorCallback);
//LLError::setTimeFunction(getRuntime); //LLError::setTimeFunction(getRuntime);
if (mSecondInstance) if (mSecondInstance)
@ -2291,66 +2246,66 @@ void LLAppViewer::initLoggingAndGetLastDuration()
} }
else else
{ {
// Remove the last ".old" log file. // Remove the last ".old" log file.
std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
"SecondLife.old"); "SecondLife.old");
LLFile::remove(old_log_file); LLFile::remove(old_log_file);
// Get name of the log file // Get name of the log file
std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
"SecondLife.log"); "SecondLife.log");
/* /*
* Before touching any log files, compute the duration of the last run * Before touching any log files, compute the duration of the last run
* by comparing the ctime of the previous start marker file with the ctime * by comparing the ctime of the previous start marker file with the ctime
* of the last log file. * of the last log file.
*/ */
std::string start_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, START_MARKER_FILE_NAME); std::string start_marker_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, START_MARKER_FILE_NAME);
llstat start_marker_stat; llstat start_marker_stat;
llstat log_file_stat; llstat log_file_stat;
std::ostringstream duration_log_stream; // can't log yet, so save any message for when we can below std::ostringstream duration_log_stream; // can't log yet, so save any message for when we can below
int start_stat_result = LLFile::stat(start_marker_file_name, &start_marker_stat); int start_stat_result = LLFile::stat(start_marker_file_name, &start_marker_stat);
int log_stat_result = LLFile::stat(log_file, &log_file_stat); int log_stat_result = LLFile::stat(log_file, &log_file_stat);
if (0 == start_stat_result && 0 == log_stat_result) if (0 == start_stat_result && 0 == log_stat_result)
{ {
int elapsed_seconds = log_file_stat.st_ctime - start_marker_stat.st_ctime; int elapsed_seconds = log_file_stat.st_ctime - start_marker_stat.st_ctime;
// only report a last run time if the last viewer was the same version // only report a last run time if the last viewer was the same version
// because this stat will be counted against this version // because this stat will be counted against this version
if (markerIsSameVersion(start_marker_file_name)) if (markerIsSameVersion(start_marker_file_name))
{ {
gLastExecDuration = elapsed_seconds; gLastExecDuration = elapsed_seconds;
} }
else else
{ {
duration_log_stream << "start marker from some other version; duration is not reported"; duration_log_stream << "start marker from some other version; duration is not reported";
gLastExecDuration = -1; gLastExecDuration = -1;
} }
} }
else else
{ {
// at least one of the LLFile::stat calls failed, so we can't compute the run time // at least one of the LLFile::stat calls failed, so we can't compute the run time
duration_log_stream << "duration stat failure; start: " << start_stat_result << " log: " << log_stat_result; duration_log_stream << "duration stat failure; start: " << start_stat_result << " log: " << log_stat_result;
gLastExecDuration = -1; // unknown gLastExecDuration = -1; // unknown
} }
std::string duration_log_msg(duration_log_stream.str()); std::string duration_log_msg(duration_log_stream.str());
// Create a new start marker file for comparison with log file time for the next run // Create a new start marker file for comparison with log file time for the next run
LLAPRFile start_marker_file; LLAPRFile start_marker_file;
start_marker_file.open(start_marker_file_name, LL_APR_WB); start_marker_file.open(start_marker_file_name, LL_APR_WB);
if (start_marker_file.getFileHandle()) if (start_marker_file.getFileHandle())
{ {
recordMarkerVersion(start_marker_file); recordMarkerVersion(start_marker_file);
start_marker_file.close(); start_marker_file.close();
} }
// Rename current log file to ".old" // Rename current log file to ".old"
LLFile::rename(log_file, old_log_file); LLFile::rename(log_file, old_log_file);
// Set the log file to SecondLife.log // Set the log file to SecondLife.log
LLError::logToFile(log_file); LLError::logToFile(log_file);
if (!duration_log_msg.empty()) if (!duration_log_msg.empty())
{ {
LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL; LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL;
} }
} }
} }
@ -3266,10 +3221,6 @@ LLSD LLAppViewer::getViewerInfo() const
info["GPU_SHADERS"] = gSavedSettings.getBOOL("RenderDeferred") ? "Enabled" : "Disabled"; info["GPU_SHADERS"] = gSavedSettings.getBOOL("RenderDeferred") ? "Enabled" : "Disabled";
info["TEXTURE_MEMORY"] = gSavedSettings.getS32("TextureMemory"); 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 #if LL_DARWIN
info["HIDPI"] = gHiDPISupport; info["HIDPI"] = gHiDPISupport;
#endif #endif
@ -3361,6 +3312,9 @@ LLSD LLAppViewer::getViewerInfo() const
info["SERVER_RELEASE_NOTES_URL"] = mServerReleaseNotesURL; 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; return info;
} }
@ -4021,8 +3975,8 @@ void LLAppViewer::removeDumpDir()
//its locking table for us. //its locking table for us.
if (gDirUtilp->dumpDirExists()) // Check if dump dir was created this run if (gDirUtilp->dumpDirExists()) // Check if dump dir was created this run
{ {
std::string dump_dir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, ""); std::string dump_dir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
gDirUtilp->deleteDirAndContents(dump_dir); gDirUtilp->deleteDirAndContents(dump_dir);
} }
if (mSecondInstance && !isError()) if (mSecondInstance && !isError())
@ -4042,7 +3996,7 @@ void LLAppViewer::forceQuit()
void LLAppViewer::fastQuit(S32 error_code) void LLAppViewer::fastQuit(S32 error_code)
{ {
// finish pending transfers // finish pending transfers
flushVFSIO(); flushLFSIO();
// let sim know we're logging out // let sim know we're logging out
sendLogoutRequest(); sendLogoutRequest();
// flush network buffers by shutting down messaging system // flush network buffers by shutting down messaging system
@ -4231,44 +4185,14 @@ void LLAppViewer::migrateCacheDirectory()
#endif // LL_WINDOWS || LL_DARWIN #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 //static
U32 LLAppViewer::getTextureCacheVersion() U32 LLAppViewer::getTextureCacheVersion()
{ {
//viewer texture cache version, change if the texture cache format changes. // Viewer texture cache version, change if the texture cache format changes.
const U32 TEXTURE_CACHE_VERSION = 8; // 2021-03-10 Bumping up by one to help obviate texture cache issues with
// Simple Cache Viewer - see SL-14985 for more information
//const U32 TEXTURE_CACHE_VERSION = 8;
const U32 TEXTURE_CACHE_VERSION = 9;
return TEXTURE_CACHE_VERSION ; return TEXTURE_CACHE_VERSION ;
} }
@ -4290,6 +4214,17 @@ bool LLAppViewer::initCache()
LLAppViewer::getTextureCache()->setReadOnly(read_only) ; LLAppViewer::getTextureCache()->setReadOnly(read_only) ;
LLVOCache::initParamSingleton(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 uintmax_t disk_cache_bytes = disk_cache_mb * 1024 * 1024;
const bool enable_cache_debug_info = gSavedSettings.getBOOL("EnableDiskCacheDebugInfo");
bool texture_cache_mismatch = false; bool texture_cache_mismatch = false;
if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion()) if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion())
{ {
@ -4324,6 +4259,7 @@ bool LLAppViewer::initCache()
LL_INFOS("AppCache") << "Cache location changed, cache needs purging" << LL_ENDL; LL_INFOS("AppCache") << "Cache location changed, cache needs purging" << LL_ENDL;
gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")); gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"));
purgeCache(); // purge old cache purgeCache(); // purge old cache
gDirUtilp->deleteDirAndContents(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name));
gSavedSettings.setString("CacheLocation", new_cache_location); gSavedSettings.setString("CacheLocation", new_cache_location);
gSavedSettings.setString("CacheLocationTopFolder", gDirUtilp->getBaseFileName(new_cache_location)); gSavedSettings.setString("CacheLocationTopFolder", gDirUtilp->getBaseFileName(new_cache_location));
} }
@ -4336,11 +4272,26 @@ bool LLAppViewer::initCache()
gSavedSettings.setString("CacheLocationTopFolder", ""); gSavedSettings.setString("CacheLocationTopFolder", "");
} }
if (mPurgeCache && !read_only) const std::string cache_dir = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, cache_dir_name);
LLDiskCache::initParamSingleton(cache_dir, disk_cache_bytes, enable_cache_debug_info);
if (!read_only)
{ {
if (mPurgeCache)
{
LLSplashScreen::update(LLTrans::getString("StartupClearingCache")); LLSplashScreen::update(LLTrans::getString("StartupClearingCache"));
purgeCache(); 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();
}
}
LLAppViewer::getPurgeDiskCacheThread()->start();
LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache")); LLSplashScreen::update(LLTrans::getString("StartupInitializingTextureCache"));
@ -4349,172 +4300,18 @@ bool LLAppViewer::initCache()
const S32 MB = 1024 * 1024; const S32 MB = 1024 * 1024;
const S64 MIN_CACHE_SIZE = 256 * MB; const S64 MIN_CACHE_SIZE = 256 * MB;
const S64 MAX_CACHE_SIZE = 9984ll * 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; S64 cache_size = (S64)(gSavedSettings.getU32("CacheSize")) * MB;
cache_size = llclamp(cache_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE); cache_size = llclamp(cache_size, MIN_CACHE_SIZE, MAX_CACHE_SIZE);
S64 vfs_size = llmin((S64)((cache_size * 2) / 10), MAX_VFS_SIZE); S64 texture_cache_size = cache_size;
S64 texture_cache_size = cache_size - vfs_size;
S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch); S64 extra = LLAppViewer::getTextureCache()->initCache(LL_PATH_CACHE, texture_cache_size, texture_cache_mismatch);
texture_cache_size -= extra; texture_cache_size -= extra;
LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion()); LLVOCache::getInstance()->initCache(LL_PATH_CACHE, gSavedSettings.getU32("CacheNumberOfRegionsForObjects"), getObjectCacheVersion());
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; return true;
}
} }
void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb) void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb)

View File

@ -1,4 +1,5 @@
/** /**
* @mainpage
* @mainpage * @mainpage
* *
* This is the sources for the Second Life Viewer; * This is the sources for the Second Life Viewer;
@ -59,6 +60,7 @@ class LLImageDecodeThread;
class LLTextureFetch; class LLTextureFetch;
class LLWatchdogTimeout; class LLWatchdogTimeout;
class LLViewerJoystick; class LLViewerJoystick;
class LLPurgeDiskCacheThread;
class LLViewerRegion; class LLViewerRegion;
extern LLTrace::BlockTimerStatHandle FTM_FRAME; extern LLTrace::BlockTimerStatHandle FTM_FRAME;
@ -85,7 +87,7 @@ public:
virtual bool frame(); // Override for application body logic virtual bool frame(); // Override for application body logic
// Application control // Application control
void flushVFSIO(); // waits for vfs transfers to complete void flushLFSIO(); // waits for lfs transfers to complete
void forceQuit(); // Puts the viewer into 'shutting down without error' mode. void forceQuit(); // Puts the viewer into 'shutting down without error' mode.
void fastQuit(S32 error_code = 0); // Shuts down the viewer immediately after sending a logout message void fastQuit(S32 error_code = 0); // Shuts down the viewer immediately after sending a logout message
void requestQuit(); // Request a quit. A kinder, gentler quit. void requestQuit(); // Request a quit. A kinder, gentler quit.
@ -118,6 +120,7 @@ public:
static LLTextureCache* getTextureCache() { return sTextureCache; } static LLTextureCache* getTextureCache() { return sTextureCache; }
static LLImageDecodeThread* getImageDecodeThread() { return sImageDecodeThread; } static LLImageDecodeThread* getImageDecodeThread() { return sImageDecodeThread; }
static LLTextureFetch* getTextureFetch() { return sTextureFetch; } static LLTextureFetch* getTextureFetch() { return sTextureFetch; }
static LLPurgeDiskCacheThread* getPurgeDiskCacheThread() { return sPurgeDiskCacheThread; }
static U32 getTextureCacheVersion() ; static U32 getTextureCacheVersion() ;
static U32 getObjectCacheVersion() ; static U32 getObjectCacheVersion() ;
@ -294,6 +297,7 @@ private:
static LLTextureCache* sTextureCache; static LLTextureCache* sTextureCache;
static LLImageDecodeThread* sImageDecodeThread; static LLImageDecodeThread* sImageDecodeThread;
static LLTextureFetch* sTextureFetch; static LLTextureFetch* sTextureFetch;
static LLPurgeDiskCacheThread* sPurgeDiskCacheThread;
S32 mNumSessions; S32 mNumSessions;
@ -389,12 +393,6 @@ extern BOOL gRestoreGL;
extern bool gUseWireframe; extern bool gUseWireframe;
extern bool gInitialDeferredModeForWireframe; extern bool gInitialDeferredModeForWireframe;
// VFS globals - gVFS is for general use
// gStaticVFS is read-only and is shipped w/ the viewer
// it has pre-cache data like the UI .TGAs
class LLVFS;
extern LLVFS *gStaticVFS;
extern LLMemoryInfo gSysMemory; extern LLMemoryInfo gSysMemory;
extern U64Bytes gMemoryAllocated; extern U64Bytes gMemoryAllocated;

View File

@ -509,7 +509,7 @@ void LLAppViewerWin32::disableWinErrorReporting()
} }
} }
const S32 MAX_CONSOLE_LINES = 500; const S32 MAX_CONSOLE_LINES = 7500;
// Only defined in newer SDKs than we currently use // Only defined in newer SDKs than we currently use
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 4 #define ENABLE_VIRTUAL_TERMINAL_PROCESSING 4

Some files were not shown because too many files have changed in this diff Show More