Merge with viewer-2.0.0-3 branch
commit
baa73fddd9
|
|
@ -14,6 +14,8 @@ Adam Marker
|
|||
VWR-2755
|
||||
Agathos Frascati
|
||||
CT-246
|
||||
CT-317
|
||||
CT-352
|
||||
Aimee Trescothick
|
||||
VWR-1813
|
||||
VWR-3321
|
||||
|
|
@ -109,6 +111,8 @@ Biancaluce Robbiani
|
|||
CT-229
|
||||
CT-230
|
||||
CT-231
|
||||
CT-321
|
||||
CT-352
|
||||
Blakar Ogre
|
||||
VWR-418
|
||||
VWR-881
|
||||
|
|
@ -129,6 +133,9 @@ Bulli Schumann
|
|||
CT-222
|
||||
CT-223
|
||||
CT-224
|
||||
CT-319
|
||||
CT-350
|
||||
CT-352
|
||||
bushing Spatula
|
||||
VWR-119
|
||||
VWR-424
|
||||
|
|
@ -179,6 +186,9 @@ Eddy Stryker
|
|||
EponymousDylan Ra
|
||||
VWR-1289
|
||||
VWR-1465
|
||||
Eva Nowicka
|
||||
CT-324
|
||||
CT-352
|
||||
Farallon Greyskin
|
||||
VWR-2036
|
||||
Feep Larsson
|
||||
|
|
@ -187,6 +197,7 @@ Feep Larsson
|
|||
VWR-4444
|
||||
Flemming Congrejo
|
||||
CT-193
|
||||
CT-318
|
||||
Fluf Fredriksson
|
||||
VWR-3450
|
||||
Fremont Cunningham
|
||||
|
|
@ -248,7 +259,12 @@ Hoze Menges
|
|||
VWR-255
|
||||
Ian Kas
|
||||
VWR-8780 (Russian localization)
|
||||
[NO JIRA] (Ukranian localization)
|
||||
[NO JIRA] (Ukranian localization)
|
||||
CT-322
|
||||
CT-325
|
||||
Irene Muni
|
||||
CT-324
|
||||
CT-352
|
||||
Iskar Ariantho
|
||||
VWR-1223
|
||||
VWR-11759
|
||||
|
|
@ -291,10 +307,15 @@ Lisa Lowe
|
|||
CT-222
|
||||
CT-223
|
||||
CT-224
|
||||
CT-319
|
||||
Lockhart Cordoso
|
||||
VWR-108
|
||||
maciek marksman
|
||||
CT-86
|
||||
Magnus Balczo
|
||||
CT-138
|
||||
Malwina Dollinger
|
||||
CT-138
|
||||
march Korda
|
||||
SVC-1020
|
||||
Matthew Dowd
|
||||
|
|
@ -333,6 +354,7 @@ Michelle2 Zenovka
|
|||
Mm Alder
|
||||
VWR-3777
|
||||
VWR-4794
|
||||
VWR-13578
|
||||
Mr Greggan
|
||||
VWR-445
|
||||
Nicholaz Beresford
|
||||
|
|
@ -437,9 +459,12 @@ Pf Shan
|
|||
CT-229
|
||||
CT-230
|
||||
CT-231
|
||||
CT-321
|
||||
princess niven
|
||||
VWR-5733
|
||||
CT-85
|
||||
CT-320
|
||||
CT-352
|
||||
Renault Clio
|
||||
VWR-1976
|
||||
Ringo Tuxing
|
||||
|
|
@ -450,6 +475,7 @@ Ringo Tuxing
|
|||
CT-229
|
||||
CT-230
|
||||
CT-231
|
||||
CT-321
|
||||
Robin Cornelius
|
||||
VWR-2488
|
||||
VWR-9557
|
||||
|
|
@ -465,6 +491,7 @@ Salahzar Stenvaag
|
|||
CT-229
|
||||
CT-230
|
||||
CT-231
|
||||
CT-321
|
||||
Sammy Frederix
|
||||
VWR-6186
|
||||
Scrippy Scofield
|
||||
|
|
@ -485,6 +512,7 @@ Sergen Davies
|
|||
CT-229
|
||||
CT-230
|
||||
CT-231
|
||||
CT-321
|
||||
SignpostMarv Martin
|
||||
VWR-153
|
||||
VWR-154
|
||||
|
|
@ -543,6 +571,8 @@ Thraxis Epsilon
|
|||
VWR-383
|
||||
tiamat bingyi
|
||||
CT-246
|
||||
TraductoresAnonimos Alter
|
||||
CT-324
|
||||
Tue Torok
|
||||
CT-68
|
||||
CT-69
|
||||
|
|
@ -554,6 +584,7 @@ Vadim Bigbear
|
|||
VWR-2681
|
||||
Vixen Heron
|
||||
VWR-2710
|
||||
CT-88
|
||||
Whoops Babii
|
||||
VWR-631
|
||||
VWR-1640
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
|
||||
# -*- cmake -*-
|
||||
|
||||
# cmake_minimum_required should appear before any
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
if (VIEWER AND WINDOWS)
|
||||
find_path(DIRECTX_INCLUDE_DIR dxdiag.h
|
||||
"$ENV{DXSDK_DIR}/Include"
|
||||
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (March 2009)/Include"
|
||||
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2008)/Include"
|
||||
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2008)/Include"
|
||||
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (March 2008)/Include"
|
||||
|
|
@ -23,6 +24,7 @@ if (VIEWER AND WINDOWS)
|
|||
|
||||
find_path(DIRECTX_LIBRARY_DIR dxguid.lib
|
||||
"$ENV{DXSDK_DIR}/Lib/x86"
|
||||
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (March 2009)/Lib/x86"
|
||||
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (August 2008)/Lib/x86"
|
||||
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (June 2008)/Lib/x86"
|
||||
"$ENV{PROGRAMFILES}/Microsoft DirectX SDK (March 2008)/Lib/x86"
|
||||
|
|
|
|||
|
|
@ -6,9 +6,11 @@ if (STANDALONE)
|
|||
else (STANDALONE)
|
||||
use_prebuilt_binary(google)
|
||||
if (WINDOWS)
|
||||
use_prebuilt_binary(google-perftools)
|
||||
set(TCMALLOC_LIBRARIES
|
||||
debug libtcmalloc_minimal-debug
|
||||
optimized libtcmalloc_minimal-debug)
|
||||
optimized libtcmalloc_minimal)
|
||||
set(GOOGLE_PERFTOOLS_FOUND "YES")
|
||||
endif (WINDOWS)
|
||||
if (LINUX)
|
||||
set(TCMALLOC_LIBRARIES tcmalloc)
|
||||
|
|
@ -27,6 +29,10 @@ endif (GOOGLE_PERFTOOLS_FOUND)
|
|||
# XXX Disable temporarily, until we have compilation issues on 64-bit
|
||||
# Etch sorted.
|
||||
set(USE_GOOGLE_PERFTOOLS OFF)
|
||||
if (WINDOWS)
|
||||
# *TODO -reenable this once we get server usage sorted out
|
||||
#set(USE_GOOGLE_PERFTOOLS ON)
|
||||
endif (WINDOWS)
|
||||
|
||||
if (USE_GOOGLE_PERFTOOLS)
|
||||
set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1)
|
||||
|
|
|
|||
|
|
@ -1,160 +1,150 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
INCLUDE(APR)
|
||||
INCLUDE(Pth)
|
||||
INCLUDE(LLMath)
|
||||
MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
|
||||
# Given a project name and a list of sourcefiles (with optional properties on each),
|
||||
# add targets to build and run the tests specified.
|
||||
# ASSUMPTIONS:
|
||||
# * this macro is being executed in the project file that is passed in
|
||||
# * current working SOURCE dir is that project dir
|
||||
# * there is a subfolder tests/ with test code corresponding to the filenames passed in
|
||||
# * properties for each sourcefile passed in indicate what libs to link that file with (MAKE NO ASSUMPTIONS ASIDE FROM TUT)
|
||||
#
|
||||
# More info and examples at: https://wiki.secondlife.com/wiki/How_to_add_unit_tests_to_indra_code
|
||||
#
|
||||
# WARNING: do NOT modify this code without working with poppy or daveh -
|
||||
# there is another branch that will conflict heavily with any changes here.
|
||||
|
||||
MACRO(ADD_BUILD_TEST_NO_COMMON name parent)
|
||||
# MESSAGE("${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
|
||||
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
|
||||
SET(no_common_libraries
|
||||
${APRUTIL_LIBRARIES}
|
||||
${APR_LIBRARIES}
|
||||
${PTHREAD_LIBRARY}
|
||||
${WINDOWS_LIBRARIES}
|
||||
)
|
||||
SET(no_common_source_files
|
||||
${name}.cpp
|
||||
tests/${name}_test.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/test.cpp
|
||||
)
|
||||
ADD_BUILD_TEST_INTERNAL("${name}" "${parent}" "${no_common_libraries}" "${no_common_source_files}")
|
||||
ENDIF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
|
||||
ENDMACRO(ADD_BUILD_TEST_NO_COMMON name parent)
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
|
||||
# Start with the header and project-wide setup before making targets
|
||||
#project(UNITTEST_PROJECT_${project})
|
||||
# Setup includes, paths, etc
|
||||
SET(alltest_SOURCE_FILES
|
||||
${CMAKE_SOURCE_DIR}/test/test.cpp
|
||||
)
|
||||
SET(alltest_DEP_TARGETS
|
||||
llcommon
|
||||
llmath
|
||||
)
|
||||
SET(alltest_INCLUDE_DIRS
|
||||
${LLMATH_INCLUDE_DIRS}
|
||||
${LLCOMMON_INCLUDE_DIRS}
|
||||
${LIBS_OPEN_DIR}/test
|
||||
)
|
||||
SET(alltest_LIBRARIES
|
||||
${PTHREAD_LIBRARY}
|
||||
${WINDOWS_LIBRARIES}
|
||||
)
|
||||
# Headers, for convenience in targets.
|
||||
SET(alltest_HEADER_FILES
|
||||
${CMAKE_SOURCE_DIR}/test/test.h
|
||||
)
|
||||
|
||||
MACRO(ADD_BUILD_TEST name parent)
|
||||
# optional extra parameter: list of additional source files
|
||||
SET(more_source_files "${ARGN}")
|
||||
# start the source test executable definitions
|
||||
SET(${project}_TEST_OUTPUT "")
|
||||
FOREACH (source ${sources})
|
||||
STRING( REGEX REPLACE "(.*)\\.[^.]+$" "\\1" name ${source} )
|
||||
STRING( REGEX REPLACE ".*\\.([^.]+)$" "\\1" extension ${source} )
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} individual source: ${source} (${name}.${extension})")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
|
||||
# MESSAGE("${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
|
||||
IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
|
||||
#
|
||||
# Per-codefile additional / external source, header, and include dir property extraction
|
||||
#
|
||||
# Source
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_SOURCE_FILES ${source} LL_TEST_ADDITIONAL_SOURCE_FILES)
|
||||
IF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
|
||||
SET(${name}_test_additional_SOURCE_FILES "")
|
||||
ENDIF(${name}_test_additional_SOURCE_FILES MATCHES NOTFOUND)
|
||||
SET(${name}_test_SOURCE_FILES ${source} tests/${name}_test.${extension} ${alltest_SOURCE_FILES} ${${name}_test_additional_SOURCE_FILES} )
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_SOURCE_FILES ${${name}_test_SOURCE_FILES}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
# Headers
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_HEADER_FILES ${source} LL_TEST_ADDITIONAL_HEADER_FILES)
|
||||
IF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
|
||||
SET(${name}_test_additional_HEADER_FILES "")
|
||||
ENDIF(${name}_test_additional_HEADER_FILES MATCHES NOTFOUND)
|
||||
SET(${name}_test_HEADER_FILES ${name}.h ${${name}_test_additional_HEADER_FILES})
|
||||
set_source_files_properties(${${name}_test_HEADER_FILES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
LIST(APPEND ${name}_test_SOURCE_FILES ${${name}_test_HEADER_FILES})
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_HEADER_FILES ${${name}_test_HEADER_FILES}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
# Include dirs
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_INCLUDE_DIRS ${source} LL_TEST_ADDITIONAL_INCLUDE_DIRS)
|
||||
IF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
|
||||
SET(${name}_test_additional_INCLUDE_DIRS "")
|
||||
ENDIF(${name}_test_additional_INCLUDE_DIRS MATCHES NOTFOUND)
|
||||
INCLUDE_DIRECTORIES(${alltest_INCLUDE_DIRS} ${name}_test_additional_INCLUDE_DIRS )
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_INCLUDE_DIRS ${${name}_test_additional_INCLUDE_DIRS}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
|
||||
SET(basic_libraries
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${LLMATH_LIBRARIES}
|
||||
${APRUTIL_LIBRARIES}
|
||||
${APR_LIBRARIES}
|
||||
${PTHREAD_LIBRARY}
|
||||
${WINDOWS_LIBRARIES}
|
||||
${PTH_LIBRARIES}
|
||||
)
|
||||
SET(basic_source_files
|
||||
${name}.cpp
|
||||
tests/${name}_test.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/test.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/lltut.cpp
|
||||
${more_source_files}
|
||||
)
|
||||
ADD_BUILD_TEST_INTERNAL("${name}" "${parent}" "${basic_libraries}" "${basic_source_files}")
|
||||
# Setup target
|
||||
ADD_EXECUTABLE(PROJECT_${project}_TEST_${name} ${${name}_test_SOURCE_FILES})
|
||||
|
||||
ENDIF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/${name}_test.cpp")
|
||||
ENDMACRO(ADD_BUILD_TEST name parent)
|
||||
|
||||
|
||||
MACRO(ADD_VIEWER_BUILD_TEST name parent)
|
||||
# This is just like the generic ADD_BUILD_TEST, but we implicitly
|
||||
# add the necessary precompiled header .cpp file (anyone else find that
|
||||
# oxymoronic?) because the MSVC build errors will NOT point you there.
|
||||
ADD_BUILD_TEST("${name}" "${parent}" llviewerprecompiledheaders.cpp)
|
||||
ENDMACRO(ADD_VIEWER_BUILD_TEST name parent)
|
||||
|
||||
|
||||
MACRO(ADD_SIMULATOR_BUILD_TEST name parent)
|
||||
ADD_BUILD_TEST("${name}" "${parent}" llsimprecompiledheaders.cpp)
|
||||
|
||||
if (WINDOWS)
|
||||
SET_SOURCE_FILES_PROPERTIES(
|
||||
"tests/${name}_test.cpp"
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS "/Yullsimprecompiledheaders.h"
|
||||
)
|
||||
endif (WINDOWS)
|
||||
ENDMACRO(ADD_SIMULATOR_BUILD_TEST name parent)
|
||||
|
||||
MACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files)
|
||||
# Optional additional parameter: pathname of Python wrapper script
|
||||
SET(wrapper "${ARGN}")
|
||||
#MESSAGE(STATUS "ADD_BUILD_TEST_INTERNAL ${name} wrapper = ${wrapper}")
|
||||
|
||||
SET(TEST_SOURCE_FILES ${source_files})
|
||||
SET(HEADER "${name}.h")
|
||||
set_source_files_properties(${HEADER}
|
||||
PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
LIST(APPEND TEST_SOURCE_FILES ${HEADER})
|
||||
INCLUDE_DIRECTORIES("${LIBS_OPEN_DIR}/test")
|
||||
ADD_EXECUTABLE(${name}_test ${TEST_SOURCE_FILES})
|
||||
TARGET_LINK_LIBRARIES(${name}_test
|
||||
${libraries}
|
||||
)
|
||||
|
||||
GET_TARGET_PROPERTY(TEST_EXE ${name}_test LOCATION)
|
||||
SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${name}_test_ok.txt)
|
||||
|
||||
SET(run_needs ${name}_test)
|
||||
|
||||
IF ("${wrapper}" STREQUAL "")
|
||||
SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
|
||||
ELSE ("${wrapper}" STREQUAL "")
|
||||
SET(TEST_CMD ${PYTHON_EXECUTABLE} ${wrapper} ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
|
||||
SET(run_needs ${run_needs} ${wrapper})
|
||||
ENDIF ("${wrapper}" STREQUAL "")
|
||||
|
||||
#MESSAGE(STATUS "ADD_BUILD_TEST_INTERNAL ${name} test_cmd = ${TEST_CMD}")
|
||||
#
|
||||
# Per-codefile additional / external project dep and lib dep property extraction
|
||||
#
|
||||
# WARNING: it's REALLY IMPORTANT to not mix these. I guarantee it will not work in the future. + poppy 2009-04-19
|
||||
# Projects
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_PROJECTS ${source} LL_TEST_ADDITIONAL_PROJECTS)
|
||||
IF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
|
||||
SET(${name}_test_additional_PROJECTS "")
|
||||
ENDIF(${name}_test_additional_PROJECTS MATCHES NOTFOUND)
|
||||
# Libraries
|
||||
GET_SOURCE_FILE_PROPERTY(${name}_test_additional_LIBRARIES ${source} LL_TEST_ADDITIONAL_LIBRARIES)
|
||||
IF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
|
||||
SET(${name}_test_additional_LIBRARIES "")
|
||||
ENDIF(${name}_test_additional_LIBRARIES MATCHES NOTFOUND)
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_PROJECTS ${${name}_test_additional_PROJECTS}")
|
||||
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS ${name}_test_additional_LIBRARIES ${${name}_test_additional_LIBRARIES}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
# Add to project
|
||||
TARGET_LINK_LIBRARIES(PROJECT_${project}_TEST_${name} ${alltest_LIBRARIES} ${alltest_DEP_TARGETS} ${${name}_test_additional_PROJECTS} ${${name}_test_additional_LIBRARIES} )
|
||||
|
||||
#
|
||||
# Setup test targets
|
||||
#
|
||||
GET_TARGET_PROPERTY(TEST_EXE PROJECT_${project}_TEST_${name} LOCATION)
|
||||
SET(TEST_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/PROJECT_${project}_TEST_${name}_ok.txt)
|
||||
SET(TEST_CMD ${TEST_EXE} --touch=${TEST_OUTPUT} --sourcedir=${CMAKE_CURRENT_SOURCE_DIR})
|
||||
# daveh - what configuration does this use? Debug? it's cmake-time, not build time. + poppy 2009-04-19
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_cmd = ${TEST_CMD}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
SET(TEST_SCRIPT_CMD
|
||||
${CMAKE_COMMAND}
|
||||
-DLD_LIBRARY_PATH=${ARCH_PREBUILT_DIRS}:/usr/lib
|
||||
-DTEST_CMD:STRING="${TEST_CMD}"
|
||||
-P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake
|
||||
)
|
||||
|
||||
#MESSAGE(STATUS "ADD_BUILD_TEST_INTERNAL ${name} test_script = ${TEST_SCRIPT_CMD}")
|
||||
IF(LL_TEST_VERBOSE)
|
||||
MESSAGE(STATUS "LL_ADD_PROJECT_UNIT_TESTS ${name} test_script = ${TEST_SCRIPT_CMD}")
|
||||
ENDIF(LL_TEST_VERBOSE)
|
||||
# Add test
|
||||
ADD_CUSTOM_COMMAND(
|
||||
OUTPUT ${TEST_OUTPUT}
|
||||
COMMAND ${TEST_SCRIPT_CMD}
|
||||
DEPENDS ${run_needs}
|
||||
DEPENDS PROJECT_${project}_TEST_${name}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
# Why not add custom target and add POST_BUILD command?
|
||||
# Slightly less uncertain behavior
|
||||
# (OUTPUT commands run non-deterministically AFAIK) + poppy 2009-04-19
|
||||
# > I did not use a post build step as I could not make it notify of a
|
||||
# > failure after the first time you build and fail a test. - daveh 2009-04-20
|
||||
LIST(APPEND ${project}_TEST_OUTPUT ${TEST_OUTPUT})
|
||||
ENDFOREACH (source)
|
||||
|
||||
ADD_CUSTOM_TARGET(${name}_test_ok ALL DEPENDS ${TEST_OUTPUT})
|
||||
IF (${parent})
|
||||
ADD_DEPENDENCIES(${parent} ${name}_test_ok)
|
||||
ENDIF (${parent})
|
||||
# Add the test runner target per-project
|
||||
# (replaces old _test_ok targets all over the place)
|
||||
ADD_CUSTOM_TARGET(${project}_tests ALL DEPENDS ${${project}_TEST_OUTPUT})
|
||||
ADD_DEPENDENCIES(${project} ${project}_tests)
|
||||
ENDMACRO(LL_ADD_PROJECT_UNIT_TESTS)
|
||||
|
||||
ENDMACRO(ADD_BUILD_TEST_INTERNAL name parent libraries source_files)
|
||||
|
||||
|
||||
MACRO(ADD_COMM_BUILD_TEST name parent wrapper)
|
||||
## MESSAGE(STATUS "ADD_COMM_BUILD_TEST ${name} wrapper = ${wrapper}")
|
||||
# optional extra parameter: list of additional source files
|
||||
SET(more_source_files "${ARGN}")
|
||||
## MESSAGE(STATUS "ADD_COMM_BUILD_TEST ${name} more_source_files = ${more_source_files}")
|
||||
|
||||
SET(libraries
|
||||
${LLMESSAGE_LIBRARIES}
|
||||
${LLMATH_LIBRARIES}
|
||||
${LLVFS_LIBRARIES}
|
||||
${LLCOMMON_LIBRARIES}
|
||||
${APRUTIL_LIBRARIES}
|
||||
${APR_LIBRARIES}
|
||||
${PTHREAD_LIBRARY}
|
||||
${WINDOWS_LIBRARIES}
|
||||
)
|
||||
SET(source_files
|
||||
${name}.cpp
|
||||
tests/${name}_test.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/test.cpp
|
||||
${CMAKE_SOURCE_DIR}/test/lltut.cpp
|
||||
${more_source_files}
|
||||
)
|
||||
|
||||
ADD_BUILD_TEST_INTERNAL("${name}" "${parent}" "${libraries}" "${source_files}" "${wrapper}")
|
||||
ENDMACRO(ADD_COMM_BUILD_TEST name parent wrapper)
|
||||
|
||||
MACRO(ADD_VIEWER_COMM_BUILD_TEST name parent wrapper)
|
||||
# This is just like the generic ADD_COMM_BUILD_TEST, but we implicitly
|
||||
# add the necessary precompiled header .cpp file (anyone else find that
|
||||
# oxymoronic?) because the MSVC build errors will NOT point you there.
|
||||
## MESSAGE(STATUS "ADD_VIEWER_COMM_BUILD_TEST ${name} wrapper = ${wrapper}")
|
||||
ADD_COMM_BUILD_TEST("${name}" "${parent}" "${wrapper}" llviewerprecompiledheaders.cpp)
|
||||
ENDMACRO(ADD_VIEWER_COMM_BUILD_TEST name parent wrapper)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ include(APR)
|
|||
include(Boost)
|
||||
include(EXPAT)
|
||||
include(ZLIB)
|
||||
include(GooglePerfTools)
|
||||
|
||||
set(LLCOMMON_INCLUDE_DIRS
|
||||
${LIBS_OPEN_DIR}/llcommon
|
||||
|
|
@ -14,6 +15,8 @@ set(LLCOMMON_INCLUDE_DIRS
|
|||
|
||||
set(LLCOMMON_LIBRARIES llcommon)
|
||||
|
||||
add_definitions(${TCMALLOC_FLAG})
|
||||
|
||||
set(LLCOMMON_LINK_SHARED OFF CACHE BOOL "Build the llcommon target as a shared library.")
|
||||
if(LLCOMMON_LINK_SHARED)
|
||||
add_definitions(-DLL_COMMON_LINK_SHARED=1)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ if (WINDOWS)
|
|||
wldap32
|
||||
gdi32
|
||||
user32
|
||||
dbghelp
|
||||
)
|
||||
else (WINDOWS)
|
||||
set(WINDOWS_LIBRARIES "")
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|||
if (ARCH STREQUAL x86_64)
|
||||
set(WORD_SIZE 64)
|
||||
else (ARCH STREQUAL x86_64)
|
||||
set(WORD_SIZE 64)
|
||||
set(WORD_SIZE 32)
|
||||
endif (ARCH STREQUAL x86_64)
|
||||
endif (WORD_SIZE EQUAL 32)
|
||||
|
||||
|
|
|
|||
|
|
@ -370,22 +370,29 @@ class LinuxSetup(UnixSetup):
|
|||
cpus += m and int(m.group(1)) or 1
|
||||
return hosts, cpus
|
||||
|
||||
def mk_distcc_hosts():
|
||||
def mk_distcc_hosts(basename, range, num_cpus):
|
||||
'''Generate a list of LL-internal machines to build on.'''
|
||||
loc_entry, cpus = localhost()
|
||||
hosts = [loc_entry]
|
||||
dead = []
|
||||
stations = [s for s in xrange(36) if s not in dead]
|
||||
stations = [s for s in xrange(range) if s not in dead]
|
||||
random.shuffle(stations)
|
||||
hosts += ['station%d.lindenlab.com/2,lzo' % s for s in stations]
|
||||
hosts += ['%s%d.lindenlab.com/%d,lzo' % (basename, s, num_cpus) for s in stations]
|
||||
cpus += 2 * len(stations)
|
||||
return ' '.join(hosts), cpus
|
||||
|
||||
if job_count is None:
|
||||
hosts, job_count = count_distcc_hosts()
|
||||
if hosts == 1 and socket.gethostname().startswith('station'):
|
||||
hosts, job_count = mk_distcc_hosts()
|
||||
os.putenv('DISTCC_HOSTS', hosts)
|
||||
if hosts == 1:
|
||||
hostname = socket.gethostname()
|
||||
if hostname.startswith('station'):
|
||||
hosts, job_count = mk_distcc_hosts('station', 36, 2)
|
||||
os.environ['DISTCC_HOSTS'] = hosts
|
||||
if hostname.startswith('eniac'):
|
||||
hosts, job_count = mk_distcc_hosts('eniac', 71, 2)
|
||||
os.environ['DISTCC_HOSTS'] = hosts
|
||||
if job_count > 12:
|
||||
job_count = 12;
|
||||
opts.extend(['-j', str(job_count)])
|
||||
|
||||
if targets:
|
||||
|
|
@ -444,7 +451,8 @@ class DarwinSetup(UnixSetup):
|
|||
targets = ' '.join(['-target ' + repr(t) for t in targets])
|
||||
else:
|
||||
targets = ''
|
||||
cmd = ('xcodebuild -parallelizeTargets '
|
||||
# cmd = ('xcodebuild -parallelizeTargets ' # parallelizeTargets is suspected of non-deterministic build failures. + poppy 2009-06-05
|
||||
cmd = ('xcodebuild '
|
||||
'-configuration %s %s %s' %
|
||||
(self.build_type, ' '.join(opts), targets))
|
||||
for d in self.build_dirs():
|
||||
|
|
@ -525,27 +533,35 @@ class WindowsSetup(PlatformSetup):
|
|||
'-DROOT_PROJECT_NAME:STRING=%(project_name)s '
|
||||
'%(opts)s "%(dir)s"' % args)
|
||||
|
||||
def get_HKLM_registry_value(self, key_str, value_str):
|
||||
import _winreg
|
||||
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
|
||||
key = _winreg.OpenKey(reg, key_str)
|
||||
value = _winreg.QueryValueEx(key, value_str)[0]
|
||||
print 'Found: %s' % value
|
||||
return value
|
||||
|
||||
def find_visual_studio(self, gen=None):
|
||||
if gen is None:
|
||||
gen = self._generator
|
||||
gen = gen.lower()
|
||||
value_str = (r'EnvironmentDirectory')
|
||||
key_str = (r'SOFTWARE\Microsoft\VisualStudio\%s\Setup\VS' %
|
||||
self.gens[gen]['ver'])
|
||||
print ('Reading VS environment from HKEY_LOCAL_MACHINE\%s\%s' %
|
||||
(key_str, value_str))
|
||||
try:
|
||||
import _winreg
|
||||
key_str = (r'SOFTWARE\Microsoft\VisualStudio\%s\Setup\VS' %
|
||||
self.gens[gen]['ver'])
|
||||
value_str = (r'EnvironmentDirectory')
|
||||
print ('Reading VS environment from HKEY_LOCAL_MACHINE\%s\%s' %
|
||||
(key_str, value_str))
|
||||
print key_str
|
||||
|
||||
reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE)
|
||||
key = _winreg.OpenKey(reg, key_str)
|
||||
value = _winreg.QueryValueEx(key, value_str)[0]
|
||||
print 'Found: %s' % value
|
||||
return value
|
||||
return self.get_HKLM_registry_value(key_str, value_str)
|
||||
except WindowsError, err:
|
||||
key_str = (r'SOFTWARE\Wow6432Node\Microsoft\VisualStudio\%s\Setup\VS' %
|
||||
self.gens[gen]['ver'])
|
||||
|
||||
try:
|
||||
return self.get_HKLM_registry_value(key_str, value_str)
|
||||
except:
|
||||
print >> sys.stderr, "Didn't find ", self.gens[gen]['gen']
|
||||
return ''
|
||||
|
||||
return ''
|
||||
|
||||
def get_build_cmd(self):
|
||||
if self.incredibuild:
|
||||
|
|
@ -689,6 +705,15 @@ Examples:
|
|||
'''
|
||||
|
||||
def main(arguments):
|
||||
if os.getenv('DISTCC_DIR') is None:
|
||||
distcc_dir = os.path.join(getcwd(), '.distcc')
|
||||
if not os.path.exists(distcc_dir):
|
||||
os.mkdir(distcc_dir)
|
||||
print "setting DISTCC_DIR to %s" % distcc_dir
|
||||
os.environ['DISTCC_DIR'] = distcc_dir
|
||||
else:
|
||||
print "DISTCC_DIR is set to %s" % os.getenv('DISTCC_DIR')
|
||||
|
||||
setup = setup_platform[sys.platform]()
|
||||
try:
|
||||
opts, args = getopt.getopt(
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ endif (DARWIN)
|
|||
target_link_libraries(llui_libtest
|
||||
llui
|
||||
${OS_LIBRARIES}
|
||||
${GOOGLE_PERFTOOLS_LIBRARIES}
|
||||
)
|
||||
|
||||
if (WINDOWS)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,53 @@
|
|||
// *TODO: switch to using TUT
|
||||
// *TODO: teach Parabuild about this program, run automatically after full builds
|
||||
|
||||
// We can't create LLImageGL objects because we have no window or rendering
|
||||
// context. Provide enough of an LLUIImage to test the LLUI library without
|
||||
// an underlying image.
|
||||
class TestUIImage : public LLUIImage
|
||||
{
|
||||
public:
|
||||
TestUIImage()
|
||||
: LLUIImage( std::string(), NULL ) // NULL ImageGL, don't deref!
|
||||
{ }
|
||||
|
||||
/*virtual*/ S32 getWidth() const
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
|
||||
/*virtual*/ S32 getHeight() const
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
};
|
||||
|
||||
// We need to supply dummy images
|
||||
class TestImageProvider : public LLImageProviderInterface
|
||||
{
|
||||
public:
|
||||
/*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name)
|
||||
{
|
||||
return makeImage();
|
||||
}
|
||||
|
||||
/*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id)
|
||||
{
|
||||
return makeImage();
|
||||
}
|
||||
|
||||
/*virtual*/ void cleanUp()
|
||||
{
|
||||
}
|
||||
|
||||
LLPointer<LLUIImage> makeImage()
|
||||
{
|
||||
LLPointer<LLImageGL> image_gl;
|
||||
LLPointer<LLUIImage> image = new LLUIImage( std::string(), image_gl);
|
||||
return image;
|
||||
}
|
||||
};
|
||||
|
||||
static std::string get_xui_dir()
|
||||
{
|
||||
std::string delim = gDirUtilp->getDirDelimiter();
|
||||
|
|
@ -84,8 +131,9 @@ int main(int argc, char** argv)
|
|||
settings["floater"] = &floater_group;
|
||||
settings["ignores"] = &ignores_group;
|
||||
|
||||
LLImageProviderInterface* image_provider = NULL;
|
||||
LLUI::initClass(settings, image_provider);
|
||||
// Don't use real images as we don't have a GL context
|
||||
TestImageProvider image_provider;
|
||||
LLUI::initClass(settings, &image_provider);
|
||||
|
||||
const bool no_register_widgets = false;
|
||||
LLWidgetReg::initClass( no_register_widgets );
|
||||
|
|
@ -116,7 +164,7 @@ int main(int argc, char** argv)
|
|||
|
||||
// Convert all test floaters to new XML format
|
||||
std::string delim = gDirUtilp->getDirDelimiter();
|
||||
std::string xui_dir = get_xui_dir() + "en-us" + delim;
|
||||
std::string xui_dir = get_xui_dir() + "en" + delim;
|
||||
std::string filename;
|
||||
while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename, false))
|
||||
{
|
||||
|
|
@ -141,8 +189,7 @@ int main(int argc, char** argv)
|
|||
llinfos << "Output: " << out_filename << llendl;
|
||||
LLFILE* floater_file = LLFile::fopen(out_filename.c_str(), "w");
|
||||
LLXMLNode::writeHeaderToFile(floater_file);
|
||||
const char* const indent = " ";
|
||||
output_node->writeToFile(floater_file, indent);
|
||||
output_node->writeToFile(floater_file);
|
||||
fclose(floater_file);
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -62,46 +62,45 @@ void LLWidgetReg::initClass(bool register_widgets)
|
|||
// references to the object files.
|
||||
if (register_widgets)
|
||||
{
|
||||
LLRegisterWidget<LLButton> button("button");
|
||||
LLRegisterWidget<LLCheckBoxCtrl> check_box("check_box");
|
||||
LLRegisterWidget<LLComboBox> combo_box("combo_box");
|
||||
LLRegisterWidget<LLFlyoutButton> flyout_button("flyout_button");
|
||||
LLRegisterWidget<LLContainerView> container_view("container_view");
|
||||
LLRegisterWidget<LLIconCtrl> icon("icon");
|
||||
LLRegisterWidget<LLLineEditor> line_editor("line_editor");
|
||||
LLRegisterWidget<LLSearchEditor> search_editor("search_editor");
|
||||
LLRegisterWidget<LLMenuItemSeparatorGL> menu_item_separator("menu_item_separator");
|
||||
LLRegisterWidget<LLMenuItemCallGL> menu_item_call_gl("menu_item_call");
|
||||
LLRegisterWidget<LLMenuItemCheckGL> menu_item_check_gl("menu_item_check");
|
||||
LLRegisterWidget<LLMenuGL> menu("menu");
|
||||
LLRegisterWidget<LLMenuBarGL> menu_bar("menu_bar");
|
||||
LLRegisterWidget<LLContextMenu> context_menu("context_menu");
|
||||
LLRegisterWidget<LLMultiSlider> multi_slider_bar("multi_slider_bar");
|
||||
LLRegisterWidget<LLMultiSliderCtrl> multi_slider("multi_slider");
|
||||
LLRegisterWidget<LLPanel> panel("panel", &LLPanel::fromXML);
|
||||
LLRegisterWidget<LLLayoutStack> layout_stack("layout_stack", &LLLayoutStack::fromXML);
|
||||
LLRegisterWidget<LLProgressBar> progress_bar("progress_bar");
|
||||
LLRegisterWidget<LLRadioGroup> radio_group("radio_group");
|
||||
LLRegisterWidget<LLRadioCtrl> radio_item("radio_item");
|
||||
LLRegisterWidget<LLScrollContainer> scroll_container("scroll_container");
|
||||
LLRegisterWidget<LLScrollingPanelList> scrolling_panel_list("scrolling_panel_list");
|
||||
LLRegisterWidget<LLScrollListCtrl> scroll_list("scroll_list");
|
||||
LLRegisterWidget<LLSlider> slider_bar("slider_bar");
|
||||
LLRegisterWidget<LLSlider> volume_slider("volume_slider");
|
||||
LLRegisterWidget<LLSliderCtrl> slider("slider");
|
||||
LLRegisterWidget<LLSpinCtrl> spinner("spinner");
|
||||
LLRegisterWidget<LLStatBar> stat_bar("stat_bar");
|
||||
//LLRegisterWidget<LLPlaceHolderPanel> placeholder("placeholder");
|
||||
LLRegisterWidget<LLTabContainer> tab_container("tab_container");
|
||||
LLRegisterWidget<LLTextBox> text("text");
|
||||
LLRegisterWidget<LLTextEditor> simple_text_editor("simple_text_editor");
|
||||
LLRegisterWidget<LLUICtrl> ui_ctrl("ui_ctrl");
|
||||
LLRegisterWidget<LLStatView> stat_view("stat_view");
|
||||
//LLRegisterWidget<LLUICtrlLocate> locate("locate");
|
||||
//LLRegisterWidget<LLUICtrlLocate> pad("pad");
|
||||
LLRegisterWidget<LLViewBorder> view_border("view_border");
|
||||
LLDefaultWidgetRegistry::Register<LLButton> button("button");
|
||||
LLDefaultWidgetRegistry::Register<LLCheckBoxCtrl> check_box("check_box");
|
||||
LLDefaultWidgetRegistry::Register<LLComboBox> combo_box("combo_box");
|
||||
LLDefaultWidgetRegistry::Register<LLFlyoutButton> flyout_button("flyout_button");
|
||||
LLDefaultWidgetRegistry::Register<LLContainerView> container_view("container_view");
|
||||
LLDefaultWidgetRegistry::Register<LLIconCtrl> icon("icon");
|
||||
LLDefaultWidgetRegistry::Register<LLLineEditor> line_editor("line_editor");
|
||||
LLDefaultWidgetRegistry::Register<LLSearchEditor> search_editor("search_editor");
|
||||
LLDefaultWidgetRegistry::Register<LLMenuItemSeparatorGL> menu_item_separator("menu_item_separator");
|
||||
LLDefaultWidgetRegistry::Register<LLMenuItemCallGL> menu_item_call_gl("menu_item_call");
|
||||
LLDefaultWidgetRegistry::Register<LLMenuItemCheckGL> menu_item_check_gl("menu_item_check");
|
||||
LLDefaultWidgetRegistry::Register<LLMenuGL> menu("menu");
|
||||
LLDefaultWidgetRegistry::Register<LLMenuBarGL> menu_bar("menu_bar");
|
||||
LLDefaultWidgetRegistry::Register<LLContextMenu> context_menu("context_menu");
|
||||
LLDefaultWidgetRegistry::Register<LLMultiSlider> multi_slider_bar("multi_slider_bar");
|
||||
LLDefaultWidgetRegistry::Register<LLMultiSliderCtrl> multi_slider("multi_slider");
|
||||
LLDefaultWidgetRegistry::Register<LLPanel> panel("panel", &LLPanel::fromXML);
|
||||
LLDefaultWidgetRegistry::Register<LLLayoutStack> layout_stack("layout_stack", &LLLayoutStack::fromXML);
|
||||
LLDefaultWidgetRegistry::Register<LLProgressBar> progress_bar("progress_bar");
|
||||
LLDefaultWidgetRegistry::Register<LLRadioGroup> radio_group("radio_group");
|
||||
LLDefaultWidgetRegistry::Register<LLRadioCtrl> radio_item("radio_item");
|
||||
LLDefaultWidgetRegistry::Register<LLScrollContainer> scroll_container("scroll_container");
|
||||
LLDefaultWidgetRegistry::Register<LLScrollingPanelList> scrolling_panel_list("scrolling_panel_list");
|
||||
LLDefaultWidgetRegistry::Register<LLScrollListCtrl> scroll_list("scroll_list");
|
||||
LLDefaultWidgetRegistry::Register<LLSlider> slider_bar("slider_bar");
|
||||
LLDefaultWidgetRegistry::Register<LLSliderCtrl> slider("slider");
|
||||
LLDefaultWidgetRegistry::Register<LLSpinCtrl> spinner("spinner");
|
||||
LLDefaultWidgetRegistry::Register<LLStatBar> stat_bar("stat_bar");
|
||||
//LLDefaultWidgetRegistry::Register<LLPlaceHolderPanel> placeholder("placeholder");
|
||||
LLDefaultWidgetRegistry::Register<LLTabContainer> tab_container("tab_container");
|
||||
LLDefaultWidgetRegistry::Register<LLTextBox> text("text");
|
||||
LLDefaultWidgetRegistry::Register<LLTextEditor> simple_text_editor("simple_text_editor");
|
||||
LLDefaultWidgetRegistry::Register<LLUICtrl> ui_ctrl("ui_ctrl");
|
||||
LLDefaultWidgetRegistry::Register<LLStatView> stat_view("stat_view");
|
||||
//LLDefaultWidgetRegistry::Register<LLUICtrlLocate> locate("locate");
|
||||
//LLDefaultWidgetRegistry::Register<LLUICtrlLocate> pad("pad");
|
||||
LLDefaultWidgetRegistry::Register<LLViewBorder> view_border("view_border");
|
||||
}
|
||||
|
||||
// *HACK: Usually this is registered as a viewer text editor
|
||||
LLRegisterWidget<LLTextEditor> text_editor("text_editor");
|
||||
LLDefaultWidgetRegistry::Register<LLTextEditor> text_editor("text_editor");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
// Register all widgets with the builder registry.
|
||||
// Useful on Windows where linker discards all references to the
|
||||
// static LLRegisterWidget<> calls.
|
||||
// static LLDefaultWidgetRegistry::Register<> calls.
|
||||
class LLWidgetReg
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ values = (
|
|||
'&<>',
|
||||
u'\u81acj',
|
||||
llsd.uri('http://foo<'),
|
||||
lluuid.LLUUID(),
|
||||
lluuid.UUID(),
|
||||
llsd.LLSD(['thing']),
|
||||
1,
|
||||
myint(31337),
|
||||
|
|
|
|||
|
|
@ -72,8 +72,11 @@ BOOL_FALSE = ('0', '0.0', 'false', '')
|
|||
|
||||
|
||||
def format_datestr(v):
|
||||
""" Formats a datetime object into the string format shared by xml and notation serializations."""
|
||||
return v.isoformat() + 'Z'
|
||||
""" Formats a datetime or date object into the string format shared by xml and notation serializations."""
|
||||
if hasattr(v, 'microsecond'):
|
||||
return v.isoformat() + 'Z'
|
||||
else:
|
||||
return v.strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
|
||||
def parse_datestr(datestr):
|
||||
"""Parses a datetime object from the string format shared by xml and notation serializations."""
|
||||
|
|
@ -183,6 +186,7 @@ class LLSDXMLFormatter(object):
|
|||
unicode : self.STRING,
|
||||
uri : self.URI,
|
||||
datetime.datetime : self.DATE,
|
||||
datetime.date : self.DATE,
|
||||
list : self.ARRAY,
|
||||
tuple : self.ARRAY,
|
||||
types.GeneratorType : self.ARRAY,
|
||||
|
|
@ -347,6 +351,7 @@ class LLSDNotationFormatter(object):
|
|||
unicode : self.STRING,
|
||||
uri : self.URI,
|
||||
datetime.datetime : self.DATE,
|
||||
datetime.date : self.DATE,
|
||||
list : self.ARRAY,
|
||||
tuple : self.ARRAY,
|
||||
types.GeneratorType : self.ARRAY,
|
||||
|
|
@ -924,12 +929,13 @@ def _format_binary_recurse(something):
|
|||
(type(something), something))
|
||||
|
||||
|
||||
def parse_binary(something):
|
||||
header = '<?llsd/binary?>\n'
|
||||
if not something.startswith(header):
|
||||
raise LLSDParseError('LLSD binary encoding header not found')
|
||||
return LLSDBinaryParser().parse(something[len(header):])
|
||||
|
||||
def parse_binary(binary):
|
||||
if binary.startswith('<?llsd/binary?>'):
|
||||
just_binary = binary.split('\n', 1)[1]
|
||||
else:
|
||||
just_binary = binary
|
||||
return LLSDBinaryParser().parse(just_binary)
|
||||
|
||||
def parse_xml(something):
|
||||
try:
|
||||
return to_python(fromstring(something)[0])
|
||||
|
|
|
|||
|
|
@ -29,25 +29,93 @@ $/LicenseInfo$
|
|||
"""
|
||||
|
||||
import sys
|
||||
from indra.base import llsd
|
||||
try:
|
||||
import syslog
|
||||
except ImportError:
|
||||
# Windows
|
||||
import sys
|
||||
class syslog(object):
|
||||
# wrap to a lame syslog for windows
|
||||
_logfp = sys.stderr
|
||||
def syslog(msg):
|
||||
_logfp.write(msg)
|
||||
if not msg.endswith('\n'):
|
||||
_logfp.write('\n')
|
||||
syslog = staticmethod(syslog)
|
||||
|
||||
_sequence_id = 0
|
||||
from indra.base.llsd import format_notation
|
||||
|
||||
def record_metrics(table, stats, dest=None):
|
||||
def record_metrics(table, stats):
|
||||
"Write a standard metrics log"
|
||||
_log("LLMETRICS", table, stats, dest)
|
||||
_log("LLMETRICS", table, stats)
|
||||
|
||||
def record_event(table, data, dest=None):
|
||||
def record_event(table, data):
|
||||
"Write a standard logmessage log"
|
||||
_log("LLLOGMESSAGE", table, data, dest)
|
||||
_log("LLLOGMESSAGE", table, data)
|
||||
|
||||
def _log(header, table, data, dest):
|
||||
def set_destination(dest):
|
||||
"""Set the destination of metrics logs for this process.
|
||||
|
||||
If you do not call this function prior to calling a logging
|
||||
method, that function will open sys.stdout as a destination.
|
||||
Attempts to set dest to None will throw a RuntimeError.
|
||||
@param dest a file-like object which will be the destination for logs."""
|
||||
if dest is None:
|
||||
# do this check here in case sys.stdout changes at some
|
||||
# point. as a default parameter, it will never be
|
||||
# re-evaluated.
|
||||
dest = sys.stdout
|
||||
raise RuntimeError("Attempt to unset metrics destination.")
|
||||
global _destination
|
||||
_destination = dest
|
||||
|
||||
def destination():
|
||||
"""Get the destination of the metrics logs for this process.
|
||||
Returns None if no destination is set"""
|
||||
global _destination
|
||||
return _destination
|
||||
|
||||
class SysLogger(object):
|
||||
"A file-like object which writes to syslog."
|
||||
def __init__(self, ident='indra', logopt = None, facility = None):
|
||||
try:
|
||||
if logopt is None:
|
||||
logopt = syslog.LOG_CONS | syslog.LOG_PID
|
||||
if facility is None:
|
||||
facility = syslog.LOG_LOCAL0
|
||||
syslog.openlog(ident, logopt, facility)
|
||||
import atexit
|
||||
atexit.register(syslog.closelog)
|
||||
except AttributeError:
|
||||
# No syslog module on Windows
|
||||
pass
|
||||
|
||||
def write(str):
|
||||
syslog.syslog(str)
|
||||
write = staticmethod(write)
|
||||
|
||||
def flush():
|
||||
pass
|
||||
flush = staticmethod(flush)
|
||||
|
||||
#
|
||||
# internal API
|
||||
#
|
||||
_sequence_id = 0
|
||||
_destination = None
|
||||
|
||||
def _next_id():
|
||||
global _sequence_id
|
||||
print >>dest, header, "(" + str(_sequence_id) + ")",
|
||||
print >>dest, table, llsd.format_notation(data)
|
||||
next = _sequence_id
|
||||
_sequence_id += 1
|
||||
return next
|
||||
|
||||
def _dest():
|
||||
global _destination
|
||||
if _destination is None:
|
||||
# this default behavior is documented in the metrics functions above.
|
||||
_destination = sys.stdout
|
||||
return _destination
|
||||
|
||||
def _log(header, table, data):
|
||||
log_line = "%s (%d) %s %s" \
|
||||
% (header, _next_id(), table, format_notation(data))
|
||||
dest = _dest()
|
||||
dest.write(log_line)
|
||||
dest.flush()
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ except:
|
|||
pass
|
||||
|
||||
_g_builder = None
|
||||
def _builder():
|
||||
global _g_builder
|
||||
if _g_builder is None:
|
||||
_g_builder = ServiceBuilder()
|
||||
return _g_builder
|
||||
|
||||
def build(name, context={}, **kwargs):
|
||||
""" Convenience method for using a global, singleton, service builder. Pass arguments either via a dict or via python keyword arguments, or both!
|
||||
|
||||
|
|
@ -56,6 +62,11 @@ def build(name, context={}, **kwargs):
|
|||
_g_builder = ServiceBuilder()
|
||||
return _g_builder.buildServiceURL(name, context, **kwargs)
|
||||
|
||||
def build_path(name, context={}, **kwargs):
|
||||
context = context.copy() # shouldn't modify the caller's dictionary
|
||||
context.update(kwargs)
|
||||
return _builder().buildPath(name, context)
|
||||
|
||||
class ServiceBuilder(object):
|
||||
def __init__(self, services_definition = services_config):
|
||||
"""\
|
||||
|
|
@ -73,12 +84,21 @@ class ServiceBuilder(object):
|
|||
continue
|
||||
if isinstance(service_builder, dict):
|
||||
# We will be constructing several builders
|
||||
for name, builder in service_builder.items():
|
||||
for name, builder in service_builder.iteritems():
|
||||
full_builder_name = service['name'] + '-' + name
|
||||
self.builders[full_builder_name] = builder
|
||||
else:
|
||||
self.builders[service['name']] = service_builder
|
||||
|
||||
def buildPath(self, name, context):
|
||||
"""\
|
||||
@brief given the environment on construction, return a service path.
|
||||
@param name The name of the service.
|
||||
@param context A dict of name value lookups for the service.
|
||||
@returns Returns the
|
||||
"""
|
||||
return russ.format(self.builders[name], context)
|
||||
|
||||
def buildServiceURL(self, name, context={}, **kwargs):
|
||||
"""\
|
||||
@brief given the environment on construction, return a service URL.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,32 @@
|
|||
"""\
|
||||
@file siesta.py
|
||||
@brief A tiny llsd based RESTful web services framework
|
||||
|
||||
$LicenseInfo:firstyear=2008&license=mit$
|
||||
|
||||
Copyright (c) 2008, Linden Research, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
$/LicenseInfo$
|
||||
"""
|
||||
|
||||
from indra.base import config
|
||||
from indra.base import llsd
|
||||
from webob import exc
|
||||
import webob
|
||||
|
|
@ -37,11 +66,11 @@ def mime_type(content_type):
|
|||
return content_type.split(';', 1)[0].strip().lower()
|
||||
|
||||
class BodyLLSD(object):
|
||||
'''Give a webob Request or Response an llsd property.
|
||||
'''Give a webob Request or Response an llsd based "content" property.
|
||||
|
||||
Getting the llsd property parses the body, and caches the result.
|
||||
Getting the content property parses the body, and caches the result.
|
||||
|
||||
Setting the llsd property formats a payload, and the body property
|
||||
Setting the content property formats a payload, and the body property
|
||||
is set.'''
|
||||
|
||||
def _llsd__get(self):
|
||||
|
|
@ -80,7 +109,7 @@ class BodyLLSD(object):
|
|||
if hasattr(self, '_llsd'):
|
||||
del self._llsd
|
||||
|
||||
llsd = property(_llsd__get, _llsd__set, _llsd__del)
|
||||
content = property(_llsd__get, _llsd__set, _llsd__del)
|
||||
|
||||
|
||||
class Response(webob.Response, BodyLLSD):
|
||||
|
|
@ -114,10 +143,10 @@ class Request(webob.Request, BodyLLSD):
|
|||
|
||||
Sensible content type and accept headers are used by default.
|
||||
|
||||
Setting the llsd property also sets the body. Getting the llsd
|
||||
Setting the content property also sets the body. Getting the content
|
||||
property parses the body if necessary.
|
||||
|
||||
If you set the body property directly, the llsd property will be
|
||||
If you set the body property directly, the content property will be
|
||||
deleted.'''
|
||||
|
||||
default_content_type = 'application/llsd+xml'
|
||||
|
|
@ -149,11 +178,11 @@ class Request(webob.Request, BodyLLSD):
|
|||
body = property(webob.Request._body__get, _body__set,
|
||||
webob.Request._body__del, webob.Request._body__get.__doc__)
|
||||
|
||||
def create_response(self, llsd=None, status='200 OK',
|
||||
def create_response(self, content=None, status='200 OK',
|
||||
conditional_response=webob.NoDefault):
|
||||
resp = self.ResponseClass(status=status, request=self,
|
||||
conditional_response=conditional_response)
|
||||
resp.llsd = llsd
|
||||
resp.content = content
|
||||
return resp
|
||||
|
||||
def curl(self):
|
||||
|
|
@ -196,12 +225,18 @@ llsd_formatters = {
|
|||
'application/xml': llsd.format_xml,
|
||||
}
|
||||
|
||||
formatter_qualities = (
|
||||
('application/llsd+xml', 1.0),
|
||||
('application/llsd+notation', 0.5),
|
||||
('application/llsd+binary', 0.4),
|
||||
('application/xml', 0.3),
|
||||
('application/json', 0.2),
|
||||
)
|
||||
|
||||
def formatter_for_mime_type(mime_type):
|
||||
'''Return a formatter that encodes to the given MIME type.
|
||||
|
||||
The result is a pair of function and MIME type.'''
|
||||
|
||||
try:
|
||||
return llsd_formatters[mime_type], mime_type
|
||||
except KeyError:
|
||||
|
|
@ -214,21 +249,19 @@ def formatter_for_request(req):
|
|||
'''Return a formatter that encodes to the preferred type of the client.
|
||||
|
||||
The result is a pair of function and actual MIME type.'''
|
||||
|
||||
for ctype in req.accept.best_matches('application/llsd+xml'):
|
||||
try:
|
||||
return llsd_formatters[ctype], ctype
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
ctype = req.accept.best_match(formatter_qualities)
|
||||
try:
|
||||
return llsd_formatters[ctype], ctype
|
||||
except KeyError:
|
||||
raise exc.HTTPNotAcceptable().exception
|
||||
|
||||
|
||||
def wsgi_adapter(func, environ, start_response):
|
||||
'''Adapt a Siesta callable to act as a WSGI application.'''
|
||||
|
||||
# Process the request as appropriate.
|
||||
try:
|
||||
req = Request(environ)
|
||||
#print req.urlvars
|
||||
resp = func(req, **req.urlvars)
|
||||
if not isinstance(resp, webob.Response):
|
||||
try:
|
||||
|
|
@ -281,7 +314,8 @@ def llsd_class(cls):
|
|||
allowed = [m for m in http11_methods
|
||||
if hasattr(instance, 'handle_' + m.lower())]
|
||||
raise exc.HTTPMethodNotAllowed(
|
||||
headers={'Allowed': ', '.join(allowed)}).exception
|
||||
headers={'Allow': ', '.join(allowed)}).exception
|
||||
#print "kwargs: ", kwargs
|
||||
return handler(req, **kwargs)
|
||||
|
||||
def replacement(environ, start_response):
|
||||
|
|
@ -336,7 +370,7 @@ def curl(reqs):
|
|||
|
||||
route_re = re.compile(r'''
|
||||
\{ # exact character "{"
|
||||
(\w+) # variable name (restricted to a-z, 0-9, _)
|
||||
(\w*) # "config" or variable (restricted to a-z, 0-9, _)
|
||||
(?:([:~])([^}]+))? # optional :type or ~regex part
|
||||
\} # exact character "}"
|
||||
''', re.VERBOSE)
|
||||
|
|
@ -344,27 +378,37 @@ route_re = re.compile(r'''
|
|||
predefined_regexps = {
|
||||
'uuid': r'[a-f0-9][a-f0-9-]{31,35}',
|
||||
'int': r'\d+',
|
||||
'host': r'[a-z0-9][a-z0-9\-\.]*',
|
||||
}
|
||||
|
||||
def compile_route(route):
|
||||
fp = StringIO()
|
||||
last_pos = 0
|
||||
for match in route_re.finditer(route):
|
||||
#print "matches: ", match.groups()
|
||||
fp.write(re.escape(route[last_pos:match.start()]))
|
||||
var_name = match.group(1)
|
||||
sep = match.group(2)
|
||||
expr = match.group(3)
|
||||
if expr:
|
||||
if sep == ':':
|
||||
expr = predefined_regexps[expr]
|
||||
# otherwise, treat what follows '~' as a regexp
|
||||
if var_name == 'config':
|
||||
expr = re.escape(str(config.get(var_name)))
|
||||
else:
|
||||
expr = '[^/]+'
|
||||
expr = '(?P<%s>%s)' % (var_name, expr)
|
||||
if expr:
|
||||
if sep == ':':
|
||||
expr = predefined_regexps[expr]
|
||||
# otherwise, treat what follows '~' as a regexp
|
||||
else:
|
||||
expr = '[^/]+'
|
||||
if var_name != '':
|
||||
expr = '(?P<%s>%s)' % (var_name, expr)
|
||||
else:
|
||||
expr = '(%s)' % (expr,)
|
||||
fp.write(expr)
|
||||
last_pos = match.end()
|
||||
fp.write(re.escape(route[last_pos:]))
|
||||
return '^%s$' % fp.getvalue()
|
||||
compiled_route = '^%s$' % fp.getvalue()
|
||||
#print route, "->", compiled_route
|
||||
return compiled_route
|
||||
|
||||
class Router(object):
|
||||
'''WSGI routing class. Parses a URL and hands off a request to
|
||||
|
|
@ -372,21 +416,43 @@ class Router(object):
|
|||
responds with a 404.'''
|
||||
|
||||
def __init__(self):
|
||||
self.routes = []
|
||||
self.paths = []
|
||||
self._new_routes = []
|
||||
self._routes = []
|
||||
self._paths = []
|
||||
|
||||
def add(self, route, app, methods=None):
|
||||
self.paths.append(route)
|
||||
self.routes.append((re.compile(compile_route(route)), app,
|
||||
methods and dict.fromkeys(methods)))
|
||||
self._new_routes.append((route, app, methods))
|
||||
|
||||
def _create_routes(self):
|
||||
for route, app, methods in self._new_routes:
|
||||
self._paths.append(route)
|
||||
self._routes.append(
|
||||
(re.compile(compile_route(route)),
|
||||
app,
|
||||
methods and dict.fromkeys(methods)))
|
||||
self._new_routes = []
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
# load up the config from the config file. Only needs to be
|
||||
# done once per interpreter. This is the entry point of all
|
||||
# siesta applications, so this is where we trap it.
|
||||
_conf = config.get_config()
|
||||
if _conf is None:
|
||||
import os.path
|
||||
fname = os.path.join(
|
||||
environ.get('ll.config_dir', '/local/linden/etc'),
|
||||
'indra.xml')
|
||||
config.load(fname)
|
||||
|
||||
# proceed with handling the request
|
||||
self._create_routes()
|
||||
path_info = environ['PATH_INFO']
|
||||
request_method = environ['REQUEST_METHOD']
|
||||
allowed = []
|
||||
for regex, app, methods in self.routes:
|
||||
for regex, app, methods in self._routes:
|
||||
m = regex.match(path_info)
|
||||
if m:
|
||||
#print "groupdict:",m.groupdict()
|
||||
if not methods or request_method in methods:
|
||||
environ['paste.urlvars'] = m.groupdict()
|
||||
return app(environ, start_response)
|
||||
|
|
@ -396,7 +462,7 @@ class Router(object):
|
|||
allowed = dict.fromkeys(allows).keys()
|
||||
allowed.sort()
|
||||
resp = exc.HTTPMethodNotAllowed(
|
||||
headers={'Allowed': ', '.join(allowed)})
|
||||
headers={'Allow': ', '.join(allowed)})
|
||||
else:
|
||||
resp = exc.HTTPNotFound()
|
||||
return resp(environ, start_response)
|
||||
|
|
|
|||
|
|
@ -48,9 +48,8 @@ from indra.base import llsd
|
|||
from indra.base import config
|
||||
|
||||
DEBUG = False
|
||||
|
||||
NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
|
||||
NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
|
||||
NQ_FILE_SUFFIX = None
|
||||
NQ_FILE_SUFFIX_LEN = None
|
||||
|
||||
_g_named_manager = None
|
||||
|
||||
|
|
@ -60,6 +59,11 @@ def _init_g_named_manager(sql_dir = None):
|
|||
|
||||
This function is intended entirely for testing purposes,
|
||||
because it's tricky to control the config from inside a test."""
|
||||
global NQ_FILE_SUFFIX
|
||||
NQ_FILE_SUFFIX = config.get('named-query-file-suffix', '.nq')
|
||||
global NQ_FILE_SUFFIX_LEN
|
||||
NQ_FILE_SUFFIX_LEN = len(NQ_FILE_SUFFIX)
|
||||
|
||||
if sql_dir is None:
|
||||
sql_dir = config.get('named-query-base-dir')
|
||||
|
||||
|
|
@ -73,11 +77,11 @@ def _init_g_named_manager(sql_dir = None):
|
|||
_g_named_manager = NamedQueryManager(
|
||||
os.path.abspath(os.path.realpath(sql_dir)))
|
||||
|
||||
def get(name):
|
||||
def get(name, schema = None):
|
||||
"Get the named query object to be used to perform queries"
|
||||
if _g_named_manager is None:
|
||||
_init_g_named_manager()
|
||||
return _g_named_manager.get(name)
|
||||
return _g_named_manager.get(name).for_schema(schema)
|
||||
|
||||
def sql(connection, name, params):
|
||||
# use module-global NamedQuery object to perform default substitution
|
||||
|
|
@ -330,6 +334,8 @@ class NamedQuery(object):
|
|||
|
||||
def for_schema(self, db_name):
|
||||
"Look trough the alternates and return the correct query"
|
||||
if db_name is None:
|
||||
return self
|
||||
try:
|
||||
return self._alternative[db_name]
|
||||
except KeyError, e:
|
||||
|
|
@ -359,10 +365,10 @@ class NamedQuery(object):
|
|||
if DEBUG:
|
||||
print "SQL:", self.sql(connection, params)
|
||||
rows = cursor.execute(full_query, params)
|
||||
|
||||
|
||||
# *NOTE: the expect_rows argument is a very cheesy way to get some
|
||||
# validation on the result set. If you want to add more expectation
|
||||
# logic, do something more object-oriented and flexible. Or use an ORM.
|
||||
# logic, do something more object-oriented and flexible. Or use an ORM.
|
||||
if(self._return_as_map):
|
||||
expect_rows = 1
|
||||
if expect_rows is not None and rows != expect_rows:
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ public:
|
|||
void updateMotions(e_update_t update_type);
|
||||
|
||||
LLAnimPauseRequest requestPause();
|
||||
BOOL areAnimationsPaused() { return mMotionController.isPaused(); }
|
||||
BOOL areAnimationsPaused() const { return mMotionController.isPaused(); }
|
||||
void setAnimTimeFactor(F32 factor) { mMotionController.setTimeFactor(factor); }
|
||||
void setTimeStep(F32 time_step) { mMotionController.setTimeStep(time_step); }
|
||||
|
||||
|
|
@ -231,9 +231,9 @@ public:
|
|||
return (mCurIterator++)->second;
|
||||
}
|
||||
|
||||
LLVisualParam* getVisualParam(S32 id)
|
||||
LLVisualParam* getVisualParam(S32 id) const
|
||||
{
|
||||
VisualParamIndexMap_t::iterator iter = mVisualParamIndexMap.find(id);
|
||||
VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.find(id);
|
||||
return (iter == mVisualParamIndexMap.end()) ? 0 : iter->second;
|
||||
}
|
||||
S32 getVisualParamID(LLVisualParam *id)
|
||||
|
|
@ -246,11 +246,11 @@ public:
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
S32 getVisualParamCount() { return (S32)mVisualParamIndexMap.size(); }
|
||||
S32 getVisualParamCount() const { return (S32)mVisualParamIndexMap.size(); }
|
||||
LLVisualParam* getVisualParam(const char *name);
|
||||
|
||||
|
||||
ESex getSex() { return mSex; }
|
||||
ESex getSex() const { return mSex; }
|
||||
void setSex( ESex sex ) { mSex = sex; }
|
||||
|
||||
U32 getAppearanceSerialNum() const { return mAppearanceSerialNum; }
|
||||
|
|
|
|||
|
|
@ -187,14 +187,6 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask)
|
|||
}
|
||||
|
||||
focus_pt += mCharacter->getCharacterPosition();
|
||||
if (!llfinite(focus_pt.magVecSquared()))
|
||||
{
|
||||
LLVector3 tmp = mCharacter->getCharacterPosition() ;
|
||||
LL_WARNS_ONCE("Animation") << "Non finite focus point in editing motion. focus point: " << focus_pt << " and character position: " <<
|
||||
tmp << " and pointAtPt: " << pointAtPt <<
|
||||
" - ignoring anim" << LL_ENDL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// propagate joint positions to kinematic chain
|
||||
mParentJoint.setPosition( mParentState->getJoint()->getWorldPosition() );
|
||||
|
|
|
|||
|
|
@ -1019,9 +1019,9 @@ bool LLMotionController::isMotionLoading(LLMotion* motion)
|
|||
//-----------------------------------------------------------------------------
|
||||
// findMotion()
|
||||
//-----------------------------------------------------------------------------
|
||||
LLMotion* LLMotionController::findMotion(const LLUUID& id)
|
||||
LLMotion* LLMotionController::findMotion(const LLUUID& id) const
|
||||
{
|
||||
motion_map_t::iterator iter = mAllMotions.find(id);
|
||||
motion_map_t::const_iterator iter = mAllMotions.find(id);
|
||||
if(iter == mAllMotions.end())
|
||||
{
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -153,12 +153,12 @@ public:
|
|||
// pause and continue all motions
|
||||
void pauseAllMotions();
|
||||
void unpauseAllMotions();
|
||||
BOOL isPaused() { return mPaused; }
|
||||
BOOL isPaused() const { return mPaused; }
|
||||
|
||||
void setTimeStep(F32 step);
|
||||
|
||||
void setTimeFactor(F32 time_factor);
|
||||
F32 getTimeFactor() { return mTimeFactor; }
|
||||
F32 getTimeFactor() const { return mTimeFactor; }
|
||||
|
||||
motion_list_t& getActiveMotions() { return mActiveMotions; }
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ public:
|
|||
//protected:
|
||||
bool isMotionActive( LLMotion *motion );
|
||||
bool isMotionLoading( LLMotion *motion );
|
||||
LLMotion *findMotion( const LLUUID& id );
|
||||
LLMotion *findMotion( const LLUUID& id ) const;
|
||||
|
||||
protected:
|
||||
// internal operations act on motion instances directly
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
virtual void stopAnimating(BOOL set_by_user);
|
||||
|
||||
// Interface methods
|
||||
S32 getID() { return mID; }
|
||||
S32 getID() const { return mID; }
|
||||
void setID(S32 id) { llassert(!mInfo); mID = id; }
|
||||
|
||||
const std::string& getName() const { return mInfo->mName; }
|
||||
|
|
@ -124,22 +124,22 @@ public:
|
|||
void setMaxDisplayName(const std::string& s) { mInfo->mMaxName = s; }
|
||||
void setMinDisplayName(const std::string& s) { mInfo->mMinName = s; }
|
||||
|
||||
EVisualParamGroup getGroup() { return mInfo->mGroup; }
|
||||
F32 getMinWeight() { return mInfo->mMinWeight; }
|
||||
F32 getMaxWeight() { return mInfo->mMaxWeight; }
|
||||
F32 getDefaultWeight() { return mInfo->mDefaultWeight; }
|
||||
ESex getSex() { return mInfo->mSex; }
|
||||
EVisualParamGroup getGroup() const { return mInfo->mGroup; }
|
||||
F32 getMinWeight() const { return mInfo->mMinWeight; }
|
||||
F32 getMaxWeight() const { return mInfo->mMaxWeight; }
|
||||
F32 getDefaultWeight() const { return mInfo->mDefaultWeight; }
|
||||
ESex getSex() const { return mInfo->mSex; }
|
||||
|
||||
F32 getWeight() { return mIsAnimating ? mTargetWeight : mCurWeight; }
|
||||
F32 getCurrentWeight() { return mCurWeight; }
|
||||
F32 getLastWeight() { return mLastWeight; }
|
||||
BOOL isAnimating() { return mIsAnimating; }
|
||||
F32 getWeight() const { return mIsAnimating ? mTargetWeight : mCurWeight; }
|
||||
F32 getCurrentWeight() const { return mCurWeight; }
|
||||
F32 getLastWeight() const { return mLastWeight; }
|
||||
BOOL isAnimating() const { return mIsAnimating; }
|
||||
|
||||
LLVisualParam* getNextParam() { return mNext; }
|
||||
void setNextParam( LLVisualParam *next );
|
||||
|
||||
virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating; }
|
||||
BOOL getAnimating() { return mIsAnimating; }
|
||||
BOOL getAnimating() const { return mIsAnimating; }
|
||||
|
||||
protected:
|
||||
F32 mCurWeight; // current weight
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ include_directories(
|
|||
# ${LLCOMMON_LIBRARIES})
|
||||
|
||||
set(llcommon_SOURCE_FILES
|
||||
llallocator.cpp
|
||||
llallocator_heap_profile.cpp
|
||||
llapp.cpp
|
||||
llapr.cpp
|
||||
llaprsockstream.cpp
|
||||
|
|
@ -47,15 +49,16 @@ set(llcommon_SOURCE_FILES
|
|||
llformat.cpp
|
||||
llframetimer.cpp
|
||||
llheartbeat.cpp
|
||||
llindraconfigfile.cpp
|
||||
llliveappconfig.cpp
|
||||
lllivefile.cpp
|
||||
lllog.cpp
|
||||
llmd5.cpp
|
||||
llmemory.cpp
|
||||
llmemorystream.cpp
|
||||
llmemtype.cpp
|
||||
llmetrics.cpp
|
||||
llmortician.cpp
|
||||
llptrto.cpp
|
||||
llprocessor.cpp
|
||||
llqueuedthread.cpp
|
||||
llrand.cpp
|
||||
|
|
@ -67,6 +70,7 @@ set(llcommon_SOURCE_FILES
|
|||
llsdutil.cpp
|
||||
llsecondlifeurls.cpp
|
||||
llstat.cpp
|
||||
llstacktrace.cpp
|
||||
llstreamtools.cpp
|
||||
llstring.cpp
|
||||
llstringtable.cpp
|
||||
|
|
@ -93,6 +97,8 @@ set(llcommon_HEADER_FILES
|
|||
indra_constants.h
|
||||
linden_common.h
|
||||
linked_lists.h
|
||||
llallocator.h
|
||||
llallocator_heap_profile.h
|
||||
llagentconstants.h
|
||||
llapp.h
|
||||
llapr.h
|
||||
|
|
@ -115,7 +121,9 @@ set(llcommon_HEADER_FILES
|
|||
lldate.h
|
||||
lldefs.h
|
||||
lldependencies.h
|
||||
lldeleteutils.h
|
||||
lldepthstack.h
|
||||
lldictionary.h
|
||||
lldlinked.h
|
||||
lldoubledispatch.h
|
||||
lldqueueptr.h
|
||||
|
|
@ -142,7 +150,7 @@ set(llcommon_HEADER_FILES
|
|||
llheartbeat.h
|
||||
llhttpstatuscodes.h
|
||||
llindexedqueue.h
|
||||
llindraconfigfile.h
|
||||
llinstancetracker.h
|
||||
llinstancetracker.h
|
||||
llkeythrottle.h
|
||||
lllazy.h
|
||||
|
|
@ -183,6 +191,7 @@ set(llcommon_HEADER_FILES
|
|||
llskiplist.h
|
||||
llskipmap.h
|
||||
llstack.h
|
||||
llstacktrace.h
|
||||
llstat.h
|
||||
llstatenums.h
|
||||
llstl.h
|
||||
|
|
@ -240,7 +249,15 @@ target_link_libraries(
|
|||
${BOOST_REGEX_LIBRARY}
|
||||
)
|
||||
|
||||
ADD_BUILD_TEST(llaprsockstream llcommon)
|
||||
ADD_BUILD_TEST(lllazy llcommon)
|
||||
ADD_BUILD_TEST(lleventfilter llcommon)
|
||||
ADD_BUILD_TEST(lleventcoro llcommon)
|
||||
include(LLAddBuildTest)
|
||||
SET(llcommon_TEST_SOURCE_FILES
|
||||
# WARNING: Please don't write tests against LLCommon or LLMath until this issue is resolved: https://jira.lindenlab.com/jira/browse/DEV-29456
|
||||
# lllazy.cpp
|
||||
)
|
||||
LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}")
|
||||
|
||||
# *TODO - reenable these once tcmalloc libs no longer break the build.
|
||||
#ADD_BUILD_TEST(llallocator llcommon)
|
||||
#ADD_BUILD_TEST(llallocator_heap_profile llcommon)
|
||||
#ADD_BUILD_TEST(llmemtype llcommon)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,140 @@
|
|||
/**
|
||||
* @file llallocator.cpp
|
||||
* @brief Implementation of the LLAllocator class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llallocator.h"
|
||||
|
||||
#if LL_USE_TCMALLOC
|
||||
|
||||
#include "google/heap-profiler.h"
|
||||
#include "google/commandlineflags_public.h"
|
||||
|
||||
DECLARE_bool(heap_profile_use_stack_trace);
|
||||
//DECLARE_double(tcmalloc_release_rate);
|
||||
|
||||
// static
|
||||
void LLAllocator::pushMemType(S32 type)
|
||||
{
|
||||
if(isProfiling())
|
||||
{
|
||||
PushMemType(type);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
S32 LLAllocator::popMemType()
|
||||
{
|
||||
if (isProfiling())
|
||||
{
|
||||
return PopMemType();
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void LLAllocator::setProfilingEnabled(bool should_enable)
|
||||
{
|
||||
// NULL disables dumping to disk
|
||||
static char const * const PREFIX = NULL;
|
||||
if(should_enable)
|
||||
{
|
||||
HeapProfilerSetUseStackTrace(false);
|
||||
HeapProfilerStart(PREFIX);
|
||||
}
|
||||
else
|
||||
{
|
||||
HeapProfilerStop();
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLAllocator::isProfiling()
|
||||
{
|
||||
return IsHeapProfilerRunning();
|
||||
}
|
||||
|
||||
std::string LLAllocator::getRawProfile()
|
||||
{
|
||||
// *TODO - fix google-perftools to accept an buffer to avoid this
|
||||
// malloc-copy-free cycle.
|
||||
char * buffer = GetHeapProfile();
|
||||
std::string ret = buffer;
|
||||
free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else // LL_USE_TCMALLOC
|
||||
|
||||
//
|
||||
// stub implementations for when tcmalloc is disabled
|
||||
//
|
||||
|
||||
// static
|
||||
void LLAllocator::pushMemType(S32 type)
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
S32 LLAllocator::popMemType()
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void LLAllocator::setProfilingEnabled(bool should_enable)
|
||||
{
|
||||
}
|
||||
|
||||
// static
|
||||
bool LLAllocator::isProfiling()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string LLAllocator::getRawProfile()
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
#endif // LL_USE_TCMALLOC
|
||||
|
||||
LLAllocatorHeapProfile const & LLAllocator::getProfile()
|
||||
{
|
||||
mProf.mLines.clear();
|
||||
|
||||
// *TODO - avoid making all these extra copies of things...
|
||||
std::string prof_text = getRawProfile();
|
||||
//std::cout << prof_text << std::endl;
|
||||
mProf.parse(prof_text);
|
||||
return mProf;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* @file llallocator.h
|
||||
* @brief Declaration of the LLAllocator class.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLALLOCATOR_H
|
||||
#define LL_LLALLOCATOR_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "llmemtype.h"
|
||||
#include "llallocator_heap_profile.h"
|
||||
|
||||
class LLAllocator {
|
||||
friend class LLMemoryView;
|
||||
friend class LLMemType;
|
||||
|
||||
private:
|
||||
static void pushMemType(S32 type);
|
||||
static S32 popMemType();
|
||||
|
||||
public:
|
||||
void setProfilingEnabled(bool should_enable);
|
||||
|
||||
static bool isProfiling();
|
||||
|
||||
LLAllocatorHeapProfile const & getProfile();
|
||||
|
||||
private:
|
||||
std::string getRawProfile();
|
||||
|
||||
private:
|
||||
LLAllocatorHeapProfile mProf;
|
||||
};
|
||||
|
||||
#endif // LL_LLALLOCATOR_H
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
/**
|
||||
* @file llallocator_heap_profile.cpp
|
||||
* @brief Implementation of the parser for tcmalloc heap profile data.
|
||||
* @author Brad Kittenbrink
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llallocator_heap_profile.h"
|
||||
|
||||
#if LL_MSVC
|
||||
// disable warning about boost::lexical_cast returning uninitialized data
|
||||
// when it fails to parse the string
|
||||
#pragma warning (disable:4701)
|
||||
#endif
|
||||
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/range/iterator_range.hpp>
|
||||
|
||||
static const std::string HEAP_PROFILE_MAGIC_STR = "heap profile:";
|
||||
|
||||
static bool is_separator(char c)
|
||||
{
|
||||
return isspace(c) || c == '[' || c == ']' || c == ':';
|
||||
}
|
||||
|
||||
void LLAllocatorHeapProfile::parse(std::string const & prof_text)
|
||||
{
|
||||
// a typedef for handling a token in the string buffer
|
||||
// it's a begin/end pair of string::const_iterators
|
||||
typedef boost::iterator_range<std::string::const_iterator> range_t;
|
||||
|
||||
mLines.clear();
|
||||
|
||||
if(prof_text.compare(0, HEAP_PROFILE_MAGIC_STR.length(), HEAP_PROFILE_MAGIC_STR) != 0)
|
||||
{
|
||||
// *TODO - determine if there should be some better error state than
|
||||
// mLines being empty. -brad
|
||||
llwarns << "invalid heap profile data passed into parser." << llendl;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector< range_t > prof_lines;
|
||||
|
||||
std::string::const_iterator prof_begin = prof_text.begin() + HEAP_PROFILE_MAGIC_STR.length();
|
||||
|
||||
range_t prof_range(prof_begin, prof_text.end());
|
||||
boost::algorithm::split(prof_lines,
|
||||
prof_range,
|
||||
boost::bind(std::equal_to<llwchar>(), '\n', _1));
|
||||
|
||||
std::vector< range_t >::const_iterator i;
|
||||
for(i = prof_lines.begin(); i != prof_lines.end() && !i->empty(); ++i)
|
||||
{
|
||||
range_t const & line_text = *i;
|
||||
|
||||
std::vector<range_t> line_elems;
|
||||
|
||||
boost::algorithm::split(line_elems,
|
||||
line_text,
|
||||
is_separator);
|
||||
|
||||
std::vector< range_t >::iterator j;
|
||||
j = line_elems.begin();
|
||||
|
||||
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
|
||||
llassert_always(j != line_elems.end());
|
||||
U32 live_count = boost::lexical_cast<U32>(*j);
|
||||
++j;
|
||||
|
||||
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
|
||||
llassert_always(j != line_elems.end());
|
||||
U64 live_size = boost::lexical_cast<U64>(*j);
|
||||
++j;
|
||||
|
||||
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
|
||||
llassert_always(j != line_elems.end());
|
||||
U32 tot_count = boost::lexical_cast<U32>(*j);
|
||||
++j;
|
||||
|
||||
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
|
||||
llassert_always(j != line_elems.end());
|
||||
U64 tot_size = boost::lexical_cast<U64>(*j);
|
||||
++j;
|
||||
|
||||
while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
|
||||
llassert_always(j != line_elems.end());
|
||||
++j; // skip the '@'
|
||||
|
||||
mLines.push_back(line(live_count, live_size, tot_count, tot_size));
|
||||
line & current_line = mLines.back();
|
||||
|
||||
for(; j != line_elems.end(); ++j)
|
||||
{
|
||||
if(!j->empty()) {
|
||||
U32 marker = boost::lexical_cast<U32>(*j);
|
||||
current_line.mTrace.push_back(marker);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// *TODO - parse MAPPED_LIBRARIES section here if we're ever interested in it
|
||||
}
|
||||
|
||||
void LLAllocatorHeapProfile::dump(std::ostream & out) const
|
||||
{
|
||||
lines_t::const_iterator i;
|
||||
for(i = mLines.begin(); i != mLines.end(); ++i)
|
||||
{
|
||||
out << i->mLiveCount << ": " << i->mLiveSize << '[' << i->mTotalCount << ": " << i->mTotalSize << "] @";
|
||||
|
||||
stack_trace::const_iterator j;
|
||||
for(j = i->mTrace.begin(); j != i->mTrace.end(); ++j)
|
||||
{
|
||||
out << ' ' << *j;
|
||||
}
|
||||
out << '\n';
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* @file llallocator_heap_profile.h
|
||||
* @brief Declaration of the parser for tcmalloc heap profile data.
|
||||
* @author Brad Kittenbrink
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLALLOCATOR_HEAP_PROFILE_H
|
||||
#define LL_LLALLOCATOR_HEAP_PROFILE_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class LLAllocatorHeapProfile
|
||||
{
|
||||
public:
|
||||
typedef int stack_marker;
|
||||
|
||||
typedef std::vector<stack_marker> stack_trace;
|
||||
|
||||
struct line {
|
||||
line(U32 live_count, U64 live_size, U32 tot_count, U64 tot_size) :
|
||||
mLiveSize(live_size),
|
||||
mTotalSize(tot_size),
|
||||
mLiveCount(live_count),
|
||||
mTotalCount(tot_count)
|
||||
{
|
||||
}
|
||||
U64 mLiveSize, mTotalSize;
|
||||
U32 mLiveCount, mTotalCount;
|
||||
stack_trace mTrace;
|
||||
};
|
||||
|
||||
typedef std::vector<line> lines_t;
|
||||
|
||||
LLAllocatorHeapProfile()
|
||||
{
|
||||
}
|
||||
|
||||
void parse(std::string const & prof_text);
|
||||
|
||||
void dump(std::ostream & out) const;
|
||||
|
||||
public:
|
||||
lines_t mLines;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_LLALLOCATOR_HEAP_PROFILE_H
|
||||
|
|
@ -38,7 +38,9 @@
|
|||
#include "llerrorcontrol.h"
|
||||
#include "llerrorthread.h"
|
||||
#include "llframetimer.h"
|
||||
#include "lllivefile.h"
|
||||
#include "llmemory.h"
|
||||
#include "llstl.h" // for DeletePointer()
|
||||
#include "lltimer.h"
|
||||
|
||||
//
|
||||
|
|
@ -91,7 +93,6 @@ LLAppChildCallback LLApp::sDefaultChildCallback = NULL;
|
|||
LLApp::LLApp() : mThreadErrorp(NULL)
|
||||
{
|
||||
commonCtor();
|
||||
startErrorThread();
|
||||
}
|
||||
|
||||
void LLApp::commonCtor()
|
||||
|
|
@ -106,9 +107,6 @@ void LLApp::commonCtor()
|
|||
sSigChildCount = new LLAtomicU32(0);
|
||||
#endif
|
||||
|
||||
// Setup error handling
|
||||
setupErrorHandling();
|
||||
|
||||
// initialize the options structure. We need to make this an array
|
||||
// because the structured data will not auto-allocate if we
|
||||
// reference an invalid location with the [] operator.
|
||||
|
|
@ -141,6 +139,11 @@ LLApp::~LLApp()
|
|||
delete sSigChildCount;
|
||||
sSigChildCount = NULL;
|
||||
#endif
|
||||
|
||||
// reclaim live file memory
|
||||
std::for_each(mLiveFiles.begin(), mLiveFiles.end(), DeletePointer());
|
||||
mLiveFiles.clear();
|
||||
|
||||
setStopped();
|
||||
// HACK: wait for the error thread to clean itself
|
||||
ms_sleep(20);
|
||||
|
|
@ -214,6 +217,15 @@ bool LLApp::parseCommandOptions(int argc, char** argv)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void LLApp::manageLiveFile(LLLiveFile* livefile)
|
||||
{
|
||||
if(!livefile) return;
|
||||
livefile->checkAndReload();
|
||||
livefile->addToEventTimer();
|
||||
mLiveFiles.push_back(livefile);
|
||||
}
|
||||
|
||||
bool LLApp::setOptionData(OptionPriority level, LLSD data)
|
||||
{
|
||||
if((level < 0)
|
||||
|
|
@ -275,6 +287,7 @@ void LLApp::setupErrorHandling()
|
|||
|
||||
#endif
|
||||
|
||||
startErrorThread();
|
||||
}
|
||||
|
||||
void LLApp::startErrorThread()
|
||||
|
|
@ -283,10 +296,13 @@ void LLApp::startErrorThread()
|
|||
// Start the error handling thread, which is responsible for taking action
|
||||
// when the app goes into the APP_STATUS_ERROR state
|
||||
//
|
||||
llinfos << "Starting error thread" << llendl;
|
||||
mThreadErrorp = new LLErrorThread();
|
||||
mThreadErrorp->setUserData((void *) this);
|
||||
mThreadErrorp->start();
|
||||
if(!mThreadErrorp)
|
||||
{
|
||||
llinfos << "Starting error thread" << llendl;
|
||||
mThreadErrorp = new LLErrorThread();
|
||||
mThreadErrorp->setUserData((void *) this);
|
||||
mThreadErrorp->start();
|
||||
}
|
||||
}
|
||||
|
||||
void LLApp::setErrorHandler(LLAppErrorHandler handler)
|
||||
|
|
|
|||
|
|
@ -40,8 +40,7 @@
|
|||
|
||||
// Forward declarations
|
||||
class LLErrorThread;
|
||||
class LLApp;
|
||||
|
||||
class LLLiveFile;
|
||||
|
||||
typedef void (*LLAppErrorHandler)();
|
||||
typedef void (*LLAppChildCallback)(int pid, bool exited, int status);
|
||||
|
|
@ -127,6 +126,19 @@ public:
|
|||
*/
|
||||
bool parseCommandOptions(int argc, char** argv);
|
||||
|
||||
/**
|
||||
* @brief Keep track of live files automatically.
|
||||
*
|
||||
* *TODO: it currently uses the <code>addToEventTimer()</code> API
|
||||
* instead of the runner. I should probalby use the runner.
|
||||
*
|
||||
* *NOTE: DO NOT add the livefile instance to any kind of check loop.
|
||||
*
|
||||
* @param livefile A valid instance of an LLLiveFile. This LLApp
|
||||
* instance will delete the livefile instance.
|
||||
*/
|
||||
void manageLiveFile(LLLiveFile* livefile);
|
||||
|
||||
/**
|
||||
* @brief Set the options at the specified priority.
|
||||
*
|
||||
|
|
@ -194,11 +206,26 @@ public:
|
|||
#endif
|
||||
static int getPid();
|
||||
|
||||
//
|
||||
// Error handling methods
|
||||
//
|
||||
/** @name Error handling methods */
|
||||
//@{
|
||||
/**
|
||||
* @brief Do our generic platform-specific error-handling setup --
|
||||
* signals on unix, structured exceptions on windows.
|
||||
*
|
||||
* DO call this method if your app will either spawn children or be
|
||||
* spawned by a launcher.
|
||||
* Call just after app object construction.
|
||||
* (Otherwise your app will crash when getting signals,
|
||||
* and will not core dump.)
|
||||
*
|
||||
* DO NOT call this method if your application has specialized
|
||||
* error handling code.
|
||||
*/
|
||||
void setupErrorHandling();
|
||||
|
||||
void setErrorHandler(LLAppErrorHandler handler);
|
||||
void setSyncErrorHandler(LLAppErrorHandler handler);
|
||||
//@}
|
||||
|
||||
#if !LL_WINDOWS
|
||||
//
|
||||
|
|
@ -214,8 +241,9 @@ public:
|
|||
void setDefaultChildCallback(LLAppChildCallback callback);
|
||||
|
||||
// Fork and do the proper signal handling/error handling mojo
|
||||
// WARNING: You need to make sure your signal handling callback is correct after
|
||||
// you fork, because not all threads are duplicated when you fork!
|
||||
// *NOTE: You need to make sure your signal handling callback is
|
||||
// correct after you fork, because not all threads are duplicated
|
||||
// when you fork!
|
||||
pid_t fork();
|
||||
#endif
|
||||
|
||||
|
|
@ -255,7 +283,6 @@ protected:
|
|||
private:
|
||||
void startErrorThread();
|
||||
|
||||
void setupErrorHandling(); // Do platform-specific error-handling setup (signals, structured exceptions)
|
||||
static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
|
||||
static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread.
|
||||
|
||||
|
|
@ -278,6 +305,8 @@ private:
|
|||
// The application options.
|
||||
LLSD mOptions;
|
||||
|
||||
// The live files for this application
|
||||
std::vector<LLLiveFile*> mLiveFiles;
|
||||
//@}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
|
||||
LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool.
|
||||
apr_thread_mutex_t *gLogMutexp = NULL;
|
||||
apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
|
||||
|
||||
const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
|
||||
|
||||
|
|
@ -51,6 +52,7 @@ void ll_init_apr()
|
|||
|
||||
// Initialize the logging mutex
|
||||
apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
|
||||
apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
|
||||
}
|
||||
|
||||
if(!LLAPRFile::sAPRFilePoolp)
|
||||
|
|
@ -72,6 +74,14 @@ void ll_cleanup_apr()
|
|||
apr_thread_mutex_destroy(gLogMutexp);
|
||||
gLogMutexp = NULL;
|
||||
}
|
||||
if (gCallStacksLogMutexp)
|
||||
{
|
||||
// Clean up the logging mutex
|
||||
|
||||
// All other threads NEED to be done before we clean up APR, so this is okay.
|
||||
apr_thread_mutex_destroy(gCallStacksLogMutexp);
|
||||
gCallStacksLogMutexp = NULL;
|
||||
}
|
||||
if (gAPRPoolp)
|
||||
{
|
||||
apr_pool_destroy(gAPRPoolp);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "llstring.h"
|
||||
|
||||
extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
|
||||
extern apr_thread_mutex_t* gCallStacksLogMutexp;
|
||||
|
||||
/**
|
||||
* @brief initialize the common apr constructs -- apr itself, the
|
||||
|
|
|
|||
|
|
@ -33,148 +33,112 @@
|
|||
#include "linden_common.h"
|
||||
|
||||
#include "llassettype.h"
|
||||
#include "lldictionary.h"
|
||||
#include "llmemory.h"
|
||||
#include "llsingleton.h"
|
||||
|
||||
#include "llstring.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
// I added lookups for exact text of asset type enums in addition to the ones below, so shoot me. -Steve
|
||||
|
||||
struct asset_info_t
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class LLAssetType
|
||||
///----------------------------------------------------------------------------
|
||||
struct AssetEntry : public LLDictionaryEntry
|
||||
{
|
||||
LLAssetType::EType type;
|
||||
const char* desc;
|
||||
AssetEntry(const char *desc_name,
|
||||
const char *type_name, // 8 character limit!
|
||||
const char *human_name,
|
||||
const char *category_name, // used by llinventorymodel when creating new categories
|
||||
EDragAndDropType dad_type);
|
||||
|
||||
// limited to 8 characters
|
||||
const char *mTypeName;
|
||||
// human readable form. Put as many printable characters you want in each one.
|
||||
// (c.f. llinventory.cpp INVENTORY_TYPE_HUMAN_NAMES).
|
||||
const char *mHumanName;
|
||||
const char *mCategoryName;
|
||||
EDragAndDropType mDadType;
|
||||
};
|
||||
|
||||
asset_info_t asset_types[] =
|
||||
class LLAssetDictionary : public LLSingleton<LLAssetDictionary>,
|
||||
public LLDictionary<LLAssetType::EType, AssetEntry>
|
||||
{
|
||||
{ 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_ROOT_CATEGORY, "ROOT_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_TRASH, "TRASH" },
|
||||
{ LLAssetType::AT_SNAPSHOT_CATEGORY, "SNAPSHOT_CATEGORY" },
|
||||
{ LLAssetType::AT_LOST_AND_FOUND, "LOST_AND_FOUND" },
|
||||
{ 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_FAVORITE, "FAVORITE" },
|
||||
{ LLAssetType::AT_NONE, "NONE" },
|
||||
public:
|
||||
LLAssetDictionary();
|
||||
};
|
||||
|
||||
LLAssetType::EType LLAssetType::getType(const std::string& sin)
|
||||
LLAssetDictionary::LLAssetDictionary()
|
||||
{
|
||||
std::string s = sin;
|
||||
addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE));
|
||||
addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND));
|
||||
addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD));
|
||||
addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK));
|
||||
addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING));
|
||||
addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT));
|
||||
addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD));
|
||||
addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY));
|
||||
addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY));
|
||||
addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT));
|
||||
addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART));
|
||||
addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed Sounds", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION));
|
||||
addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE));
|
||||
addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", "New Folder", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE));
|
||||
addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE));
|
||||
};
|
||||
|
||||
AssetEntry::AssetEntry(const char *desc_name,
|
||||
const char *type_name,
|
||||
const char *human_name,
|
||||
const char *category_name,
|
||||
EDragAndDropType dad_type) :
|
||||
LLDictionaryEntry(desc_name),
|
||||
mTypeName(type_name),
|
||||
mHumanName(human_name),
|
||||
mCategoryName(category_name),
|
||||
mDadType(dad_type)
|
||||
{
|
||||
llassert(strlen(mTypeName) <= 8);
|
||||
}
|
||||
|
||||
// static
|
||||
LLAssetType::EType LLAssetType::getType(const std::string& desc_name)
|
||||
{
|
||||
std::string s = desc_name;
|
||||
LLStringUtil::toUpper(s);
|
||||
for (S32 idx = 0; ;idx++)
|
||||
{
|
||||
asset_info_t* info = asset_types + idx;
|
||||
if (info->type == LLAssetType::AT_NONE)
|
||||
break;
|
||||
if (s == info->desc)
|
||||
return info->type;
|
||||
}
|
||||
return LLAssetType::AT_NONE;
|
||||
return LLAssetDictionary::getInstance()->lookup(s);
|
||||
}
|
||||
|
||||
std::string LLAssetType::getDesc(LLAssetType::EType type)
|
||||
// static
|
||||
const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type)
|
||||
{
|
||||
for (S32 idx = 0; ;idx++)
|
||||
{
|
||||
asset_info_t* info = asset_types + idx;
|
||||
if (type == info->type)
|
||||
return info->desc;
|
||||
if (info->type == LLAssetType::AT_NONE)
|
||||
break;
|
||||
const AssetEntry *entry = LLAssetDictionary::getInstance()->lookup(asset_type);
|
||||
if (entry)
|
||||
{
|
||||
return entry->mName;
|
||||
}
|
||||
else
|
||||
{
|
||||
static const std::string error_string = "BAD TYPE";
|
||||
return error_string;
|
||||
}
|
||||
return "BAD TYPE";
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
// The asset type names are limited to 8 characters.
|
||||
// static
|
||||
const char* LLAssetType::mAssetTypeNames[LLAssetType::AT_COUNT] =
|
||||
{
|
||||
"texture",
|
||||
"sound",
|
||||
"callcard",
|
||||
"landmark",
|
||||
"script",
|
||||
"clothing",
|
||||
"object",
|
||||
"notecard",
|
||||
"category",
|
||||
"root",
|
||||
"lsltext",
|
||||
"lslbyte",
|
||||
"txtr_tga",// Intentionally spelled this way. Limited to eight characters.
|
||||
"bodypart",
|
||||
"trash",
|
||||
"snapshot",
|
||||
"lstndfnd",
|
||||
"snd_wav",
|
||||
"img_tga",
|
||||
"jpeg",
|
||||
"animatn",
|
||||
"gesture",
|
||||
"simstate",
|
||||
"favorite"
|
||||
};
|
||||
|
||||
// This table is meant for decoding to human readable form. Put any
|
||||
// and as many printable characters you want in each one.
|
||||
// See also llinventory.cpp INVENTORY_TYPE_HUMAN_NAMES
|
||||
const char* LLAssetType::mAssetTypeHumanNames[LLAssetType::AT_COUNT] =
|
||||
{
|
||||
"texture",
|
||||
"sound",
|
||||
"calling card",
|
||||
"landmark",
|
||||
"legacy script",
|
||||
"clothing",
|
||||
"object",
|
||||
"note card",
|
||||
"folder",
|
||||
"root",
|
||||
"lsl2 script",
|
||||
"lsl bytecode",
|
||||
"tga texture",
|
||||
"body part",
|
||||
"trash",
|
||||
"snapshot",
|
||||
"lost and found",
|
||||
"sound",
|
||||
"targa image",
|
||||
"jpeg image",
|
||||
"animation",
|
||||
"gesture",
|
||||
"simstate"
|
||||
"favorite"
|
||||
};
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// class LLAssetType
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
// static
|
||||
const char* LLAssetType::lookup( LLAssetType::EType type )
|
||||
const char *LLAssetType::lookup(LLAssetType::EType asset_type)
|
||||
{
|
||||
if( (type >= 0) && (type < AT_COUNT ))
|
||||
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
|
||||
const AssetEntry *entry = dict->lookup(asset_type);
|
||||
if (entry)
|
||||
{
|
||||
return mAssetTypeNames[ S32( type ) ];
|
||||
return entry->mTypeName;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -188,25 +152,30 @@ LLAssetType::EType LLAssetType::lookup( const char* name )
|
|||
return lookup(ll_safe_string(name));
|
||||
}
|
||||
|
||||
LLAssetType::EType LLAssetType::lookup( const std::string& name )
|
||||
LLAssetType::EType LLAssetType::lookup(const std::string& type_name)
|
||||
{
|
||||
for( S32 i = 0; i < AT_COUNT; i++ )
|
||||
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
|
||||
for (LLAssetDictionary::const_iterator iter = dict->begin();
|
||||
iter != dict->end();
|
||||
iter++)
|
||||
{
|
||||
if( name == mAssetTypeNames[i] )
|
||||
const AssetEntry *entry = iter->second;
|
||||
if (type_name == entry->mTypeName)
|
||||
{
|
||||
// match
|
||||
return (EType)i;
|
||||
return iter->first;
|
||||
}
|
||||
}
|
||||
return AT_NONE;
|
||||
}
|
||||
|
||||
// static
|
||||
const char* LLAssetType::lookupHumanReadable(LLAssetType::EType type)
|
||||
const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type)
|
||||
{
|
||||
if( (type >= 0) && (type < AT_COUNT ))
|
||||
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
|
||||
const AssetEntry *entry = dict->lookup(asset_type);
|
||||
if (entry)
|
||||
{
|
||||
return mAssetTypeHumanNames[S32(type)];
|
||||
return entry->mHumanName;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -220,44 +189,51 @@ LLAssetType::EType LLAssetType::lookupHumanReadable( const char* name )
|
|||
return lookupHumanReadable(ll_safe_string(name));
|
||||
}
|
||||
|
||||
LLAssetType::EType LLAssetType::lookupHumanReadable( const std::string& name )
|
||||
LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_name)
|
||||
{
|
||||
for( S32 i = 0; i < AT_COUNT; i++ )
|
||||
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
|
||||
for (LLAssetDictionary::const_iterator iter = dict->begin();
|
||||
iter != dict->end();
|
||||
iter++)
|
||||
{
|
||||
if( name == mAssetTypeHumanNames[i] )
|
||||
const AssetEntry *entry = iter->second;
|
||||
if (readable_name == entry->mHumanName)
|
||||
{
|
||||
// match
|
||||
return (EType)i;
|
||||
return iter->first;
|
||||
}
|
||||
}
|
||||
return AT_NONE;
|
||||
}
|
||||
|
||||
EDragAndDropType LLAssetType::lookupDragAndDropType( EType asset )
|
||||
// static
|
||||
const char *LLAssetType::lookupCategoryName(LLAssetType::EType asset_type)
|
||||
{
|
||||
switch( asset )
|
||||
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
|
||||
const AssetEntry *entry = dict->lookup(asset_type);
|
||||
if (entry)
|
||||
{
|
||||
case AT_TEXTURE: return DAD_TEXTURE;
|
||||
case AT_SOUND: return DAD_SOUND;
|
||||
case AT_CALLINGCARD: return DAD_CALLINGCARD;
|
||||
case AT_LANDMARK: return DAD_LANDMARK;
|
||||
case AT_SCRIPT: return DAD_NONE;
|
||||
case AT_CLOTHING: return DAD_CLOTHING;
|
||||
case AT_OBJECT: return DAD_OBJECT;
|
||||
case AT_NOTECARD: return DAD_NOTECARD;
|
||||
case AT_CATEGORY: return DAD_CATEGORY;
|
||||
case AT_ROOT_CATEGORY: return DAD_ROOT_CATEGORY;
|
||||
case AT_LSL_TEXT: return DAD_SCRIPT;
|
||||
case AT_BODYPART: return DAD_BODYPART;
|
||||
case AT_ANIMATION: return DAD_ANIMATION;
|
||||
case AT_GESTURE: return DAD_GESTURE;
|
||||
default: return DAD_NONE;
|
||||
};
|
||||
return entry->mCategoryName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "New Folder";
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
EDragAndDropType LLAssetType::lookupDragAndDropType(EType asset_type)
|
||||
{
|
||||
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
|
||||
const AssetEntry *entry = dict->lookup(asset_type);
|
||||
if (entry)
|
||||
return entry->mDadType;
|
||||
else
|
||||
return DAD_NONE;
|
||||
}
|
||||
|
||||
// static. Generate a good default description
|
||||
void LLAssetType::generateDescriptionFor(LLAssetType::EType type,
|
||||
std::string& desc)
|
||||
void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type,
|
||||
std::string& description)
|
||||
{
|
||||
const S32 BUF_SIZE = 30;
|
||||
char time_str[BUF_SIZE]; /* Flawfinder: ignore */
|
||||
|
|
@ -265,6 +241,6 @@ void LLAssetType::generateDescriptionFor(LLAssetType::EType type,
|
|||
time(&now);
|
||||
memset(time_str, '\0', BUF_SIZE);
|
||||
strftime(time_str, BUF_SIZE - 1, "%Y-%m-%d %H:%M:%S ", localtime(&now));
|
||||
desc.assign(time_str);
|
||||
desc.append(LLAssetType::lookupHumanReadable(type));
|
||||
description.assign(time_str);
|
||||
description.append(LLAssetType::lookupHumanReadable(asset_type));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,152 +30,154 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLASSETTYPE
|
||||
#define LL_LLASSETTYPE
|
||||
#ifndef LL_LLASSETTYPE_H
|
||||
#define LL_LLASSETTYPE_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "stdenums.h" // for EDragAndDropType
|
||||
|
||||
class LL_COMMON_API LLAssetType
|
||||
class LLAssetType
|
||||
{
|
||||
public:
|
||||
enum EType
|
||||
{
|
||||
// Used for painting the faces of geometry.
|
||||
// Stored in typical j2c stream format
|
||||
AT_TEXTURE = 0,
|
||||
// Used for painting the faces of geometry.
|
||||
// Stored in typical j2c stream format.
|
||||
|
||||
// Used to fill the aural spectrum.
|
||||
AT_SOUND = 1,
|
||||
// Used to fill the aural spectrum.
|
||||
|
||||
// Links instant message access to the user on the card. eg, a
|
||||
// card for yourself, a card for linden support, a card for
|
||||
// the guy you were talking to in the coliseum.
|
||||
AT_CALLINGCARD = 2,
|
||||
// Links instant message access to the user on the card.
|
||||
// : E.G. A card for yourself, for linden support, for
|
||||
// : the guy you were talking to in the coliseum.
|
||||
|
||||
// Links to places in the world with location and a screen
|
||||
// shot or image saved. eg, home, linden headquarters, the
|
||||
// coliseum, or destinations where we want to increase
|
||||
// traffic.
|
||||
AT_LANDMARK = 3,
|
||||
// Links to places in the world with location and a screen shot or image saved.
|
||||
// : E.G. Home, linden headquarters, the coliseum, destinations where
|
||||
// : we want to increase traffic.
|
||||
|
||||
// Valid scripts that can be attached to an object. eg. open a
|
||||
// door, jump into the air.
|
||||
AT_SCRIPT = 4,
|
||||
// Valid scripts that can be attached to an object.
|
||||
// : E.G. Open a door, jump into the air.
|
||||
|
||||
// A collection of textures and parameters that can be worn
|
||||
// by an avatar.
|
||||
AT_CLOTHING = 5,
|
||||
// A collection of textures and parameters that can be worn by an avatar.
|
||||
|
||||
// Any combination of textures, sounds, and scripts that are
|
||||
// associated with a fixed piece of geometry. eg, a hot tub, a
|
||||
// house with working door.
|
||||
AT_OBJECT = 6,
|
||||
// Any combination of textures, sounds, and scripts that are
|
||||
// associated with a fixed piece of geometry.
|
||||
// : E.G. A hot tub, a house with working door.
|
||||
|
||||
// Just text
|
||||
AT_NOTECARD = 7,
|
||||
// Just text.
|
||||
|
||||
// A category holds a collection of inventory items. It's
|
||||
// treated as an item in the inventory, and therefore needs a
|
||||
// type.
|
||||
AT_CATEGORY = 8,
|
||||
// Holds a collection of inventory items.
|
||||
// It's treated as an item in the inventory and therefore needs a type.
|
||||
|
||||
// A root category is a user's root inventory category. We
|
||||
// decided to expose it visually, so it seems logical to fold
|
||||
// it into the asset types.
|
||||
AT_ROOT_CATEGORY = 9,
|
||||
// A user's root inventory category.
|
||||
// We decided to expose it visually, so it seems logical to fold
|
||||
// it into the asset types.
|
||||
|
||||
// The LSL is the brand spanking new scripting language. We've
|
||||
// split it into a text and bytecode representation.
|
||||
AT_LSL_TEXT = 10,
|
||||
AT_LSL_BYTECODE = 11,
|
||||
// The LSL is the scripting language.
|
||||
// We've split it into a text and bytecode representation.
|
||||
|
||||
// uncompressed TGA texture
|
||||
AT_TEXTURE_TGA = 12,
|
||||
// Uncompressed TGA texture.
|
||||
|
||||
// A collection of textures and parameters that can be worn
|
||||
// by an avatar.
|
||||
AT_BODYPART = 13,
|
||||
// A collection of textures and parameters that can be worn by an avatar.
|
||||
|
||||
// This asset type is meant to only be used as a marker for a
|
||||
// category preferred type. Using this, we can throw things in
|
||||
// the trash before completely deleting.
|
||||
AT_TRASH = 14,
|
||||
// Only to be used as a marker for a category preferred type.
|
||||
// Using this, we can throw things in the trash before completely deleting.
|
||||
|
||||
// This is a marker for a folder meant for snapshots. No
|
||||
// actual assets will be snapshots, though if there were, you
|
||||
// could interpret them as textures.
|
||||
AT_SNAPSHOT_CATEGORY = 15,
|
||||
// A marker for a folder meant for snapshots.
|
||||
// No actual assets will be snapshots, though if there were, you
|
||||
// could interpret them as textures.
|
||||
|
||||
// This is used to stuff lost&found items into
|
||||
AT_LOST_AND_FOUND = 16,
|
||||
// Used to stuff lost&found items into.
|
||||
|
||||
// uncompressed sound
|
||||
AT_SOUND_WAV = 17,
|
||||
// Uncompressed sound.
|
||||
|
||||
// uncompressed image, non-square, and not appropriate for use
|
||||
// as a texture.
|
||||
AT_IMAGE_TGA = 18,
|
||||
// Uncompressed image, non-square.
|
||||
// Not appropriate for use as a texture.
|
||||
|
||||
// compressed image, non-square, and not appropriate for use
|
||||
// as a texture.
|
||||
AT_IMAGE_JPEG = 19,
|
||||
// Compressed image, non-square.
|
||||
// Not appropriate for use as a texture.
|
||||
|
||||
// animation
|
||||
AT_ANIMATION = 20,
|
||||
// Animation.
|
||||
|
||||
// gesture, sequence of animations, sounds, chat, wait steps
|
||||
AT_GESTURE = 21,
|
||||
// Gesture, sequence of animations, sounds, chat, wait steps.
|
||||
|
||||
// simstate file
|
||||
AT_SIMSTATE = 22,
|
||||
|
||||
// favorite items
|
||||
AT_FAVORITE = 23,
|
||||
// Simstate file.
|
||||
|
||||
AT_LINK = 23,
|
||||
// Inventory symbolic link
|
||||
|
||||
AT_FAVORITE = 24,
|
||||
// favorite items
|
||||
|
||||
// +*********************************************+
|
||||
// | TO ADD AN ELEMENT TO THIS ENUM: |
|
||||
// +*********************************************+
|
||||
// +************************************************+
|
||||
// | 1. INSERT BEFORE AT_COUNT |
|
||||
// | 2. INCREMENT AT_COUNT BY 1 |
|
||||
// | 3. ADD TO LLAssetType::mAssetTypeNames |
|
||||
// | 4. ADD TO LLAssetType::mAssetTypeHumanNames |
|
||||
// +*********************************************+
|
||||
|
||||
AT_COUNT = 24,
|
||||
AT_COUNT = 25,
|
||||
|
||||
AT_NONE = -1
|
||||
};
|
||||
|
||||
// machine transation between type and strings
|
||||
static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate
|
||||
static EType lookup(const std::string& name);
|
||||
static const char* lookup(EType type);
|
||||
static EType lookup(const std::string& type_name);
|
||||
static const char* lookup(EType asset_type);
|
||||
|
||||
// translation from a type to a human readable form.
|
||||
static EType lookupHumanReadable( const char* name ); // safe conversion to std::string, *TODO: deprecate
|
||||
static EType lookupHumanReadable( const std::string& name );
|
||||
static const char* lookupHumanReadable(EType type);
|
||||
static EType lookupHumanReadable(const char* desc_name); // safe conversion to std::string, *TODO: deprecate
|
||||
static EType lookupHumanReadable(const std::string& readable_name);
|
||||
static const char* lookupHumanReadable(EType asset_type);
|
||||
|
||||
static EDragAndDropType lookupDragAndDropType( EType );
|
||||
static const char* lookupCategoryName(EType asset_type);
|
||||
|
||||
// Generate a good default description. You may want to add a verb
|
||||
// or agent name after this depending on your application.
|
||||
static void generateDescriptionFor(LLAssetType::EType type,
|
||||
std::string& desc);
|
||||
static void generateDescriptionFor(LLAssetType::EType asset_type,
|
||||
std::string& description);
|
||||
|
||||
static EType getType(const std::string& sin);
|
||||
static std::string getDesc(EType type);
|
||||
static EType getType(const std::string& desc_name);
|
||||
static const std::string& getDesc(EType asset_type);
|
||||
static EDragAndDropType lookupDragAndDropType(EType asset_type);
|
||||
|
||||
/* TODO: Change return types from "const char *" to "const std::string &".
|
||||
This is fairly straightforward, but requires changing some calls to use .c_str().
|
||||
e.g.:
|
||||
- fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
|
||||
+ fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType).c_str());
|
||||
*/
|
||||
|
||||
private:
|
||||
// don't instantiate or derive one of these objects
|
||||
LLAssetType( void ) {}
|
||||
~LLAssetType( void ) {}
|
||||
|
||||
private:
|
||||
static const char* mAssetTypeNames[];
|
||||
static const char* mAssetTypeHumanNames[];
|
||||
LLAssetType() {}
|
||||
~LLAssetType() {}
|
||||
};
|
||||
|
||||
#endif // LL_LLASSETTYPE
|
||||
#endif // LL_LLASSETTYPE_H
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
*/
|
||||
typedef boost::tokenizer<boost::char_separator<char> > boost_tokenizer;
|
||||
|
||||
// Useful combiner for boost signals that retturn a vool (e.g. validation)
|
||||
// Useful combiner for boost signals that return a bool (e.g. validation)
|
||||
// returns false if any of the callbacks return false
|
||||
struct boost_boolean_combiner
|
||||
{
|
||||
|
|
|
|||
|
|
@ -142,6 +142,14 @@ public:
|
|||
bool operator!=(const LLDate& rhs) const { return (*this < rhs) || (rhs < *this); }
|
||||
bool operator==(const LLDate& rhs) const { return !(*this != rhs); }
|
||||
|
||||
/**
|
||||
* @brief Compare to epoch UTC.
|
||||
*/
|
||||
|
||||
bool isNull() const { return mSecondsSinceEpoch == 0.0; }
|
||||
bool notNull() const { return mSecondsSinceEpoch != 0.0; }
|
||||
|
||||
|
||||
private:
|
||||
F64 mSecondsSinceEpoch;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* @file lldeleteutils.h
|
||||
* @brief Utility functions to simplify some common pointer-munging idioms.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
#ifndef LL_DELETE_UTILS_H
|
||||
#define LL_DELETE_UTILS_H
|
||||
|
||||
// Simple utility functions to eventually replace the common 2-line
|
||||
// idiom scattered throughout the viewer codebase. Note that where
|
||||
// possible we would rather be using smart pointers of some sort.
|
||||
|
||||
template <class T>
|
||||
inline void deleteAndClear(T*& ptr)
|
||||
{
|
||||
delete ptr;
|
||||
ptr = NULL;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void deleteAndClearArray(T*& array_ptr)
|
||||
{
|
||||
delete[] array_ptr;
|
||||
array_ptr = NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* @file lldictionary.h
|
||||
* @brief Lldictionary class header file
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2002-2007, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlife.com/developers/opensource/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at http://secondlife.com/developers/opensource/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLDICTIONARY_H
|
||||
#define LL_LLDICTIONARY_H
|
||||
|
||||
#include <map>
|
||||
|
||||
struct LLDictionaryEntry
|
||||
{
|
||||
LLDictionaryEntry(const std::string &name) :
|
||||
mName(name)
|
||||
{
|
||||
mNameCapitalized = mName;
|
||||
LLStringUtil::replaceChar(mNameCapitalized, '-', ' ');
|
||||
LLStringUtil::replaceChar(mNameCapitalized, '_', ' ');
|
||||
for (U32 i=0; i < mNameCapitalized.size(); i++)
|
||||
{
|
||||
if (i == 0 || mNameCapitalized[i-1] == ' ') // don't change ordering of this statement or crash
|
||||
{
|
||||
mNameCapitalized[i] = toupper(mNameCapitalized[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual ~LLDictionaryEntry() {}
|
||||
const std::string mName;
|
||||
std::string mNameCapitalized;
|
||||
};
|
||||
|
||||
template <class Index, class Entry>
|
||||
class LLDictionary : public std::map<Index, Entry *>
|
||||
{
|
||||
public:
|
||||
typedef std::map<Index, Entry *> map_t;
|
||||
typedef typename map_t::iterator iterator_t;
|
||||
typedef typename map_t::const_iterator const_iterator_t;
|
||||
|
||||
LLDictionary() {}
|
||||
virtual ~LLDictionary()
|
||||
{
|
||||
for (iterator_t iter = map_t::begin(); iter != map_t::end(); ++iter)
|
||||
delete (iter->second);
|
||||
}
|
||||
|
||||
const Entry *lookup(Index index) const
|
||||
{
|
||||
const_iterator_t dictionary_iter = map_t::find(index);
|
||||
if (dictionary_iter == map_t::end()) return NULL;
|
||||
return dictionary_iter->second;
|
||||
}
|
||||
const Index lookup(const std::string &name) const
|
||||
{
|
||||
for (const_iterator_t dictionary_iter = map_t::begin();
|
||||
dictionary_iter != map_t::end();
|
||||
dictionary_iter++)
|
||||
{
|
||||
const Entry *entry = dictionary_iter->second;
|
||||
if (entry->mName == name)
|
||||
{
|
||||
return dictionary_iter->first;
|
||||
}
|
||||
}
|
||||
llassert(false);
|
||||
return Index(-1);
|
||||
}
|
||||
|
||||
protected:
|
||||
void addEntry(Index index, Entry *entry)
|
||||
{
|
||||
(*this)[index] = entry;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // LL_LLDICTIONARY_H
|
||||
|
|
@ -289,7 +289,7 @@ namespace
|
|||
public:
|
||||
static LogControlFile& fromDirectory(const std::string& dir);
|
||||
|
||||
virtual void loadFile();
|
||||
virtual bool loadFile();
|
||||
|
||||
private:
|
||||
LogControlFile(const std::string &filename)
|
||||
|
|
@ -317,7 +317,7 @@ namespace
|
|||
// NB: This instance is never freed
|
||||
}
|
||||
|
||||
void LogControlFile::loadFile()
|
||||
bool LogControlFile::loadFile()
|
||||
{
|
||||
LLSD configuration;
|
||||
|
||||
|
|
@ -333,12 +333,13 @@ namespace
|
|||
llwarns << filename() << " missing, ill-formed,"
|
||||
" or simply undefined; not changing configuration"
|
||||
<< llendl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LLError::configure(configuration);
|
||||
llinfos << "logging reconfigured from " << filename() << llendl;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1228,9 +1229,62 @@ namespace LLError
|
|||
char** LLCallStacks::sBuffer = NULL ;
|
||||
S32 LLCallStacks::sIndex = 0 ;
|
||||
|
||||
class CallStacksLogLock
|
||||
{
|
||||
public:
|
||||
CallStacksLogLock();
|
||||
~CallStacksLogLock();
|
||||
bool ok() const { return mOK; }
|
||||
private:
|
||||
bool mLocked;
|
||||
bool mOK;
|
||||
};
|
||||
|
||||
CallStacksLogLock::CallStacksLogLock()
|
||||
: mLocked(false), mOK(false)
|
||||
{
|
||||
if (!gCallStacksLogMutexp)
|
||||
{
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const int MAX_RETRIES = 5;
|
||||
for (int attempts = 0; attempts < MAX_RETRIES; ++attempts)
|
||||
{
|
||||
apr_status_t s = apr_thread_mutex_trylock(gCallStacksLogMutexp);
|
||||
if (!APR_STATUS_IS_EBUSY(s))
|
||||
{
|
||||
mLocked = true;
|
||||
mOK = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ms_sleep(1);
|
||||
}
|
||||
|
||||
// We're hosed, we can't get the mutex. Blah.
|
||||
std::cerr << "CallStacksLogLock::CallStacksLogLock: failed to get mutex for log"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
CallStacksLogLock::~CallStacksLogLock()
|
||||
{
|
||||
if (mLocked)
|
||||
{
|
||||
apr_thread_mutex_unlock(gCallStacksLogMutexp);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLCallStacks::push(const char* function, const int line)
|
||||
{
|
||||
CallStacksLogLock lock;
|
||||
if (!lock.ok())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!sBuffer)
|
||||
{
|
||||
sBuffer = new char*[512] ;
|
||||
|
|
@ -1266,6 +1320,12 @@ namespace LLError
|
|||
//static
|
||||
void LLCallStacks::end(std::ostringstream* _out)
|
||||
{
|
||||
CallStacksLogLock lock;
|
||||
if (!lock.ok())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!sBuffer)
|
||||
{
|
||||
sBuffer = new char*[512] ;
|
||||
|
|
@ -1288,6 +1348,12 @@ namespace LLError
|
|||
//static
|
||||
void LLCallStacks::print()
|
||||
{
|
||||
CallStacksLogLock lock;
|
||||
if (!lock.ok())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(sIndex > 0)
|
||||
{
|
||||
llinfos << " ************* PRINT OUT LL CALL STACKS ************* " << llendl ;
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <stdexcept>
|
||||
#include <boost/signals2.hpp>
|
||||
|
|
@ -27,9 +28,13 @@
|
|||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/utility.hpp> // noncopyable
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
#include <boost/visit_each.hpp>
|
||||
#include <boost/ref.hpp> // reference_wrapper
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/preprocessor/repetition/enum_params.hpp>
|
||||
#include <boost/preprocessor/iteration/local.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include "llsd.h"
|
||||
|
|
@ -106,9 +111,6 @@ typedef LLStandardSignal::slot_type LLEventListener;
|
|||
/// Result of registering a listener, supports <tt>connected()</tt>,
|
||||
/// <tt>disconnect()</tt> and <tt>blocked()</tt>
|
||||
typedef boost::signals2::connection LLBoundListener;
|
||||
/// Storing an LLBoundListener in LLTempBoundListener will disconnect the
|
||||
/// referenced listener when the LLTempBoundListener instance is destroyed.
|
||||
typedef boost::signals2::scoped_connection LLTempBoundListener;
|
||||
|
||||
/**
|
||||
* A common idiom for event-based code is to accept either a callable --
|
||||
|
|
@ -125,7 +127,7 @@ typedef boost::signals2::scoped_connection LLTempBoundListener;
|
|||
* LLListenerOrPumpName::Empty. Test for this condition beforehand using
|
||||
* either <tt>if (param)</tt> or <tt>if (! param)</tt>.
|
||||
*/
|
||||
class LL_COMMON_API LLListenerOrPumpName
|
||||
class LLListenerOrPumpName
|
||||
{
|
||||
public:
|
||||
/// passing string name of LLEventPump
|
||||
|
|
@ -172,13 +174,13 @@ private:
|
|||
/*****************************************************************************
|
||||
* LLEventPumps
|
||||
*****************************************************************************/
|
||||
class LL_COMMON_API LLEventPump;
|
||||
class LLEventPump;
|
||||
|
||||
/**
|
||||
* LLEventPumps is a Singleton manager through which one typically accesses
|
||||
* this subsystem.
|
||||
*/
|
||||
class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>
|
||||
class LLEventPumps: public LLSingleton<LLEventPumps>
|
||||
{
|
||||
friend class LLSingleton<LLEventPumps>;
|
||||
public:
|
||||
|
|
@ -252,62 +254,14 @@ namespace LLEventDetail
|
|||
const ConnectFunc& connect_func);
|
||||
} // namespace LLEventDetail
|
||||
|
||||
/*****************************************************************************
|
||||
* LLEventTrackable
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* LLEventTrackable wraps boost::signals2::trackable, which resembles
|
||||
* boost::trackable. Derive your listener class from LLEventTrackable instead,
|
||||
* and use something like
|
||||
* <tt>LLEventPump::listen(boost::bind(&YourTrackableSubclass::method,
|
||||
* instance, _1))</tt>. This will implicitly disconnect when the object
|
||||
* referenced by @c instance is destroyed.
|
||||
*
|
||||
* @note
|
||||
* LLEventTrackable doesn't address a couple of cases:
|
||||
* * Object destroyed during call
|
||||
* - You enter a slot call in thread A.
|
||||
* - Thread B destroys the object, which of course disconnects it from any
|
||||
* future slot calls.
|
||||
* - Thread A's call uses 'this', which now refers to a defunct object.
|
||||
* Undefined behavior results.
|
||||
* * Call during destruction
|
||||
* - @c MySubclass is derived from LLEventTrackable.
|
||||
* - @c MySubclass registers one of its own methods using
|
||||
* <tt>LLEventPump::listen()</tt>.
|
||||
* - The @c MySubclass object begins destruction. <tt>~MySubclass()</tt>
|
||||
* runs, destroying state specific to the subclass. (For instance, a
|
||||
* <tt>Foo*</tt> data member is <tt>delete</tt>d but not zeroed.)
|
||||
* - The listening method will not be disconnected until
|
||||
* <tt>~LLEventTrackable()</tt> runs.
|
||||
* - Before we get there, another thread posts data to the @c LLEventPump
|
||||
* instance, calling the @c MySubclass method.
|
||||
* - The method in question relies on valid @c MySubclass state. (For
|
||||
* instance, it attempts to dereference the <tt>Foo*</tt> pointer that was
|
||||
* <tt>delete</tt>d but not zeroed.)
|
||||
* - Undefined behavior results.
|
||||
* If you suspect you may encounter any such scenario, you're better off
|
||||
* managing the lifespan of your object with <tt>boost::shared_ptr</tt>.
|
||||
* Passing <tt>LLEventPump::listen()</tt> a <tt>boost::bind()</tt> expression
|
||||
* involving a <tt>boost::weak_ptr<Foo></tt> is recognized specially, engaging
|
||||
* thread-safe Boost.Signals2 machinery.
|
||||
*/
|
||||
typedef boost::signals2::trackable LLEventTrackable;
|
||||
|
||||
/*****************************************************************************
|
||||
* LLEventPump
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* LLEventPump is the base class interface through which we access the
|
||||
* concrete subclasses LLEventStream and LLEventQueue.
|
||||
*
|
||||
* @NOTE
|
||||
* LLEventPump derives from LLEventTrackable so that when you "chain"
|
||||
* LLEventPump instances together, they will automatically disconnect on
|
||||
* destruction. Please see LLEventTrackable documentation for situations in
|
||||
* which this may be perilous across threads.
|
||||
*/
|
||||
class LL_COMMON_API LLEventPump: public LLEventTrackable
|
||||
class LLEventPump: boost::noncopyable
|
||||
{
|
||||
public:
|
||||
/**
|
||||
|
|
@ -410,22 +364,10 @@ public:
|
|||
* themselves. listen() can throw any ListenError; see ListenError
|
||||
* subclasses.
|
||||
*
|
||||
* The listener name must be unique among active listeners for this
|
||||
* LLEventPump, else you get DupListenerName. If you don't care to invent
|
||||
* a name yourself, use inventName(). (I was tempted to recognize e.g. ""
|
||||
* and internally generate a distinct name for that case. But that would
|
||||
* handle badly the scenario in which you want to add, remove, re-add,
|
||||
* etc. the same listener: each new listen() call would necessarily
|
||||
* perform a new dependency sort. Assuming you specify the same
|
||||
* after/before lists each time, using inventName() when you first
|
||||
* instantiate your listener, then passing the same name on each listen()
|
||||
* call, allows us to optimize away the second and subsequent dependency
|
||||
* sorts.
|
||||
*
|
||||
* If (as is typical) you pass a <tt>boost::bind()</tt> expression as @a
|
||||
* listener, listen() will inspect the components of that expression. If a
|
||||
* bound object matches any of several cases, the connection will
|
||||
* automatically be disconnected when that object is destroyed.
|
||||
* If (as is typical) you pass a <tt>boost::bind()</tt> expression,
|
||||
* listen() will inspect the components of that expression. If a bound
|
||||
* object matches any of several cases, the connection will automatically
|
||||
* be disconnected when that object is destroyed.
|
||||
*
|
||||
* * You bind a <tt>boost::weak_ptr</tt>.
|
||||
* * Binding a <tt>boost::shared_ptr</tt> that way would ensure that the
|
||||
|
|
@ -487,9 +429,6 @@ public:
|
|||
/// query
|
||||
virtual bool enabled() const { return mEnabled; }
|
||||
|
||||
/// Generate a distinct name for a listener -- see listen()
|
||||
static std::string inventName(const std::string& pfx="listener");
|
||||
|
||||
private:
|
||||
friend class LLEventPumps;
|
||||
/// flush queued events
|
||||
|
|
@ -528,7 +467,7 @@ protected:
|
|||
* LLEventStream is a thin wrapper around LLStandardSignal. Posting an
|
||||
* event immediately calls all registered listeners.
|
||||
*/
|
||||
class LL_COMMON_API LLEventStream: public LLEventPump
|
||||
class LLEventStream: public LLEventPump
|
||||
{
|
||||
public:
|
||||
LLEventStream(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
|
||||
|
|
@ -545,7 +484,7 @@ public:
|
|||
* LLEventQueue isa LLEventPump whose post() method defers calling registered
|
||||
* listeners until flush() is called.
|
||||
*/
|
||||
class LL_COMMON_API LLEventQueue: public LLEventPump
|
||||
class LLEventQueue: public LLEventPump
|
||||
{
|
||||
public:
|
||||
LLEventQueue(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
|
||||
|
|
@ -564,89 +503,47 @@ private:
|
|||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* LLReqID
|
||||
* LLEventTrackable and underpinnings
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* This class helps the implementer of a given event API to honor the
|
||||
* ["reqid"] convention. By this convention, each event API stamps into its
|
||||
* response LLSD a ["reqid"] key whose value echoes the ["reqid"] value, if
|
||||
* any, from the corresponding request.
|
||||
*
|
||||
* This supports an (atypical, but occasionally necessary) use case in which
|
||||
* two or more asynchronous requests are multiplexed onto the same ["reply"]
|
||||
* LLEventPump. Since the response events could arrive in arbitrary order, the
|
||||
* caller must be able to demux them. It does so by matching the ["reqid"]
|
||||
* value in each response with the ["reqid"] value in the corresponding
|
||||
* request.
|
||||
*
|
||||
* It is the caller's responsibility to ensure distinct ["reqid"] values for
|
||||
* that case. Though LLSD::UUID is guaranteed to work, it might be overkill:
|
||||
* the "namespace" of unique ["reqid"] values is simply the set of requests
|
||||
* specifying the same ["reply"] LLEventPump name.
|
||||
*
|
||||
* Making a given event API echo the request's ["reqid"] into the response is
|
||||
* nearly trivial. This helper is mostly for mnemonic purposes, to serve as a
|
||||
* place to put these comments. We hope that each time a coder implements a
|
||||
* new event API based on some existing one, s/he will say, "Huh, what's an
|
||||
* LLReqID?" and look up this material.
|
||||
*
|
||||
* The hardest part about the convention is deciding where to store the
|
||||
* ["reqid"] value. Ironically, LLReqID can't help with that: you must store
|
||||
* an LLReqID instance in whatever storage will persist until the reply is
|
||||
* sent. For example, if the request ultimately ends up using a Responder
|
||||
* subclass, storing an LLReqID instance in the Responder works.
|
||||
* LLEventTrackable wraps boost::signals2::trackable, which resembles
|
||||
* boost::trackable. Derive your listener class from LLEventTrackable instead,
|
||||
* and use something like
|
||||
* <tt>LLEventPump::listen(boost::bind(&YourTrackableSubclass::method,
|
||||
* instance, _1))</tt>. This will implicitly disconnect when the object
|
||||
* referenced by @c instance is destroyed.
|
||||
*
|
||||
* @note
|
||||
* The @em implementer of an event API must honor the ["reqid"] convention.
|
||||
* However, the @em caller of an event API need only use it if s/he is sharing
|
||||
* the same ["reply"] LLEventPump for two or more asynchronous event API
|
||||
* requests.
|
||||
*
|
||||
* In most cases, it's far easier for the caller to instantiate a local
|
||||
* LLEventStream and pass its name to the event API in question. Then it's
|
||||
* perfectly reasonable not to set a ["reqid"] key in the request, ignoring
|
||||
* the @c isUndefined() ["reqid"] value in the response.
|
||||
* LLEventTrackable doesn't address a couple of cases:
|
||||
* * Object destroyed during call
|
||||
* - You enter a slot call in thread A.
|
||||
* - Thread B destroys the object, which of course disconnects it from any
|
||||
* future slot calls.
|
||||
* - Thread A's call uses 'this', which now refers to a defunct object.
|
||||
* Undefined behavior results.
|
||||
* * Call during destruction
|
||||
* - @c MySubclass is derived from LLEventTrackable.
|
||||
* - @c MySubclass registers one of its own methods using
|
||||
* <tt>LLEventPump::listen()</tt>.
|
||||
* - The @c MySubclass object begins destruction. <tt>~MySubclass()</tt>
|
||||
* runs, destroying state specific to the subclass. (For instance, a
|
||||
* <tt>Foo*</tt> data member is <tt>delete</tt>d but not zeroed.)
|
||||
* - The listening method will not be disconnected until
|
||||
* <tt>~LLEventTrackable()</tt> runs.
|
||||
* - Before we get there, another thread posts data to the @c LLEventPump
|
||||
* instance, calling the @c MySubclass method.
|
||||
* - The method in question relies on valid @c MySubclass state. (For
|
||||
* instance, it attempts to dereference the <tt>Foo*</tt> pointer that was
|
||||
* <tt>delete</tt>d but not zeroed.)
|
||||
* - Undefined behavior results.
|
||||
* If you suspect you may encounter any such scenario, you're better off
|
||||
* managing the lifespan of your object with <tt>boost::shared_ptr</tt>.
|
||||
* Passing <tt>LLEventPump::listen()</tt> a <tt>boost::bind()</tt> expression
|
||||
* involving a <tt>boost::weak_ptr<Foo></tt> is recognized specially, engaging
|
||||
* thread-safe Boost.Signals2 machinery.
|
||||
*/
|
||||
class LLReqID
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* If you have the request in hand at the time you instantiate the
|
||||
* LLReqID, pass that request to extract its ["reqid"].
|
||||
*/
|
||||
LLReqID(const LLSD& request):
|
||||
mReqid(request["reqid"])
|
||||
{}
|
||||
/// If you don't yet have the request, use setFrom() later.
|
||||
LLReqID() {}
|
||||
typedef boost::signals2::trackable LLEventTrackable;
|
||||
|
||||
/// Extract and store the ["reqid"] value from an incoming request.
|
||||
void setFrom(const LLSD& request)
|
||||
{
|
||||
mReqid = request["reqid"];
|
||||
}
|
||||
|
||||
/// Set ["reqid"] key into a pending response LLSD object.
|
||||
void stamp(LLSD& response) const;
|
||||
|
||||
/// Make a whole new response LLSD object with our ["reqid"].
|
||||
LLSD makeResponse() const
|
||||
{
|
||||
LLSD response;
|
||||
stamp(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
/// Not really sure of a use case for this accessor...
|
||||
LLSD getReqID() const { return mReqid; }
|
||||
|
||||
private:
|
||||
LLSD mReqid;
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* Underpinnings
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* We originally provided a suite of overloaded
|
||||
* LLEventTrackable::listenTo(LLEventPump&, ...) methods that would call
|
||||
|
|
|
|||
|
|
@ -30,229 +30,323 @@
|
|||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLFASTTIMER_H
|
||||
#define LL_LLFASTTIMER_H
|
||||
#ifndef LL_FASTTIMER_H
|
||||
#define LL_FASTTIMER_H
|
||||
|
||||
#include "llinstancetracker.h"
|
||||
|
||||
#define FAST_TIMER_ON 1
|
||||
|
||||
U64 LL_COMMON_API get_cpu_clock_count();
|
||||
U64 get_cpu_clock_count();
|
||||
|
||||
class LL_COMMON_API LLFastTimer
|
||||
class LLMutex;
|
||||
|
||||
#include <queue>
|
||||
#include "llsd.h"
|
||||
|
||||
|
||||
class LLFastTimer
|
||||
{
|
||||
public:
|
||||
enum EFastTimerType
|
||||
// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
|
||||
class NamedTimer
|
||||
: public LLInstanceTracker<NamedTimer>
|
||||
{
|
||||
// high level
|
||||
FTM_FRAME,
|
||||
FTM_UPDATE,
|
||||
FTM_RENDER,
|
||||
FTM_SWAP,
|
||||
FTM_CLIENT_COPY,
|
||||
FTM_IDLE,
|
||||
FTM_SLEEP,
|
||||
public:
|
||||
~NamedTimer();
|
||||
|
||||
// common messaging components
|
||||
FTM_PUMP,
|
||||
FTM_CURL,
|
||||
enum { HISTORY_NUM = 60 };
|
||||
|
||||
const std::string& getName() { return mName; }
|
||||
NamedTimer* getParent() { return mParent; }
|
||||
void setParent(NamedTimer* parent);
|
||||
S32 getDepth();
|
||||
std::string getToolTip(S32 history_index = -1);
|
||||
|
||||
typedef std::vector<NamedTimer*>::const_iterator child_const_iter;
|
||||
child_const_iter beginChildren();
|
||||
child_const_iter endChildren();
|
||||
std::vector<NamedTimer*>& getChildren();
|
||||
|
||||
void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
|
||||
bool getCollapsed() { return mCollapsed; }
|
||||
|
||||
U64 getCountAverage() { return mCountAverage; }
|
||||
U64 getCallAverage() { return mCallAverage; }
|
||||
|
||||
U64 getHistoricalCount(S32 history_index = 0);
|
||||
U64 getHistoricalCalls(S32 history_index = 0);
|
||||
|
||||
static NamedTimer& getRootNamedTimer();
|
||||
|
||||
struct FrameState
|
||||
{
|
||||
FrameState(NamedTimer* timerp);
|
||||
|
||||
U64 mSelfTimeCounter;
|
||||
U64 mLastStartTime; // most recent time when this timer was started
|
||||
U32 mCalls;
|
||||
FrameState* mParent; // info for caller timer
|
||||
FrameState* mLastCaller; // used to bootstrap tree construction
|
||||
NamedTimer* mTimer;
|
||||
U16 mActiveCount; // number of timers with this ID active on stack
|
||||
bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
|
||||
};
|
||||
|
||||
FrameState& getFrameStateFast() const
|
||||
{
|
||||
return (*sTimerInfos)[mFrameStateIndex];
|
||||
}
|
||||
|
||||
S32 getFrameStateIndex() const { return mFrameStateIndex; }
|
||||
|
||||
FrameState& getFrameState() const;
|
||||
|
||||
|
||||
private:
|
||||
friend class LLFastTimer;
|
||||
friend class NamedTimerFactory;
|
||||
|
||||
//
|
||||
// methods
|
||||
//
|
||||
NamedTimer(const std::string& name);
|
||||
// recursive call to gather total time from children
|
||||
static void accumulateTimings();
|
||||
|
||||
// called once per frame by LLFastTimer
|
||||
static void processFrame();
|
||||
|
||||
static void buildHierarchy();
|
||||
static void resetFrame();
|
||||
static void reset();
|
||||
|
||||
typedef std::vector<FrameState> info_list_t;
|
||||
static info_list_t& getFrameStateList();
|
||||
static void createFrameStateList(); // must call before any call to getFrameStateList()
|
||||
|
||||
// common simulation components
|
||||
FTM_UPDATE_ANIMATION,
|
||||
FTM_UPDATE_TERRAIN,
|
||||
FTM_UPDATE_PRIMITIVES,
|
||||
FTM_UPDATE_PARTICLES,
|
||||
FTM_SIMULATE_PARTICLES,
|
||||
FTM_UPDATE_SKY,
|
||||
FTM_UPDATE_TEXTURES,
|
||||
FTM_UPDATE_WLPARAM,
|
||||
FTM_UPDATE_WATER,
|
||||
FTM_UPDATE_CLOUDS,
|
||||
FTM_UPDATE_GRASS,
|
||||
FTM_UPDATE_TREE,
|
||||
FTM_UPDATE_AVATAR,
|
||||
|
||||
// common render components
|
||||
FTM_SHADOW_GEOMETRY,
|
||||
FTM_SHADOW_RENDER,
|
||||
FTM_SHADOW_TERRAIN,
|
||||
FTM_SHADOW_AVATAR,
|
||||
FTM_SHADOW_SIMPLE,
|
||||
FTM_SHADOW_ALPHA,
|
||||
FTM_SHADOW_TREE,
|
||||
|
||||
FTM_RENDER_GEOMETRY,
|
||||
FTM_RENDER_TERRAIN,
|
||||
FTM_RENDER_SIMPLE,
|
||||
FTM_RENDER_FULLBRIGHT,
|
||||
FTM_RENDER_GLOW,
|
||||
FTM_RENDER_GRASS,
|
||||
FTM_RENDER_INVISIBLE,
|
||||
FTM_RENDER_SHINY,
|
||||
FTM_RENDER_BUMP,
|
||||
FTM_RENDER_TREES,
|
||||
FTM_RENDER_CHARACTERS,
|
||||
FTM_RENDER_OCCLUSION,
|
||||
FTM_RENDER_ALPHA,
|
||||
FTM_RENDER_CLOUDS,
|
||||
FTM_RENDER_HUD,
|
||||
FTM_RENDER_PARTICLES,
|
||||
FTM_RENDER_WATER,
|
||||
FTM_RENDER_WL_SKY,
|
||||
FTM_RENDER_FAKE_VBO_UPDATE,
|
||||
FTM_RENDER_TIMER,
|
||||
FTM_RENDER_UI,
|
||||
FTM_RENDER_BLOOM,
|
||||
FTM_RENDER_BLOOM_FBO,
|
||||
FTM_RENDER_FONTS,
|
||||
|
||||
// newview specific
|
||||
FTM_MESSAGES,
|
||||
FTM_MOUSEHANDLER,
|
||||
FTM_KEYHANDLER,
|
||||
FTM_REBUILD,
|
||||
FTM_STATESORT,
|
||||
FTM_STATESORT_DRAWABLE,
|
||||
FTM_STATESORT_POSTSORT,
|
||||
FTM_REBUILD_VBO,
|
||||
FTM_REBUILD_VOLUME_VB,
|
||||
FTM_REBUILD_BRIDGE_VB,
|
||||
FTM_REBUILD_HUD_VB,
|
||||
FTM_REBUILD_TERRAIN_VB,
|
||||
FTM_REBUILD_WATER_VB,
|
||||
FTM_REBUILD_TREE_VB,
|
||||
FTM_REBUILD_PARTICLE_VB,
|
||||
FTM_REBUILD_CLOUD_VB,
|
||||
FTM_REBUILD_GRASS_VB,
|
||||
FTM_REBUILD_NONE_VB,
|
||||
FTM_REBUILD_OCCLUSION_VB,
|
||||
FTM_POOLS,
|
||||
FTM_POOLRENDER,
|
||||
FTM_IDLE_CB,
|
||||
FTM_WORLD_UPDATE,
|
||||
FTM_UPDATE_MOVE,
|
||||
FTM_OCTREE_BALANCE,
|
||||
FTM_UPDATE_LIGHTS,
|
||||
FTM_CULL,
|
||||
FTM_CULL_REBOUND,
|
||||
FTM_FRUSTUM_CULL,
|
||||
FTM_GEO_UPDATE,
|
||||
FTM_GEO_RESERVE,
|
||||
FTM_GEO_LIGHT,
|
||||
FTM_GEO_SHADOW,
|
||||
FTM_GEO_SKY,
|
||||
FTM_GEN_VOLUME,
|
||||
FTM_GEN_TRIANGLES,
|
||||
FTM_GEN_FLEX,
|
||||
FTM_AUDIO_UPDATE,
|
||||
FTM_RESET_DRAWORDER,
|
||||
FTM_OBJECTLIST_UPDATE,
|
||||
FTM_AVATAR_UPDATE,
|
||||
FTM_JOINT_UPDATE,
|
||||
FTM_ATTACHMENT_UPDATE,
|
||||
FTM_LOD_UPDATE,
|
||||
FTM_REGION_UPDATE,
|
||||
FTM_CLEANUP,
|
||||
FTM_NETWORK,
|
||||
FTM_IDLE_NETWORK,
|
||||
FTM_CREATE_OBJECT,
|
||||
FTM_LOAD_AVATAR,
|
||||
FTM_PROCESS_MESSAGES,
|
||||
FTM_PROCESS_OBJECTS,
|
||||
FTM_PROCESS_IMAGES,
|
||||
FTM_IMAGE_UPDATE,
|
||||
FTM_IMAGE_CREATE,
|
||||
FTM_IMAGE_DECODE,
|
||||
FTM_IMAGE_MARK_DIRTY,
|
||||
FTM_PIPELINE,
|
||||
FTM_VFILE_WAIT,
|
||||
FTM_FLEXIBLE_UPDATE,
|
||||
FTM_OCCLUSION_READBACK,
|
||||
FTM_HUD_EFFECTS,
|
||||
FTM_HUD_UPDATE,
|
||||
FTM_INVENTORY,
|
||||
FTM_AUTO_SELECT,
|
||||
FTM_ARRANGE,
|
||||
FTM_FILTER,
|
||||
FTM_REFRESH,
|
||||
FTM_SORT,
|
||||
FTM_PICK,
|
||||
|
||||
// Temp
|
||||
FTM_TEMP1,
|
||||
FTM_TEMP2,
|
||||
FTM_TEMP3,
|
||||
FTM_TEMP4,
|
||||
FTM_TEMP5,
|
||||
FTM_TEMP6,
|
||||
FTM_TEMP7,
|
||||
FTM_TEMP8,
|
||||
|
||||
FTM_OTHER, // Special, used by display code
|
||||
|
||||
FTM_NUM_TYPES
|
||||
//
|
||||
// members
|
||||
//
|
||||
S32 mFrameStateIndex;
|
||||
|
||||
std::string mName;
|
||||
|
||||
U64 mTotalTimeCounter;
|
||||
|
||||
U64 mCountAverage;
|
||||
U64 mCallAverage;
|
||||
|
||||
U64* mCountHistory;
|
||||
U64* mCallHistory;
|
||||
|
||||
// tree structure
|
||||
NamedTimer* mParent; // NamedTimer of caller(parent)
|
||||
std::vector<NamedTimer*> mChildren;
|
||||
bool mCollapsed; // don't show children
|
||||
bool mNeedsSorting; // sort children whenever child added
|
||||
|
||||
static info_list_t* sTimerInfos;
|
||||
};
|
||||
enum { FTM_HISTORY_NUM = 60 };
|
||||
enum { FTM_MAX_DEPTH = 64 };
|
||||
|
||||
|
||||
// used to statically declare a new named timer
|
||||
class DeclareTimer
|
||||
{
|
||||
public:
|
||||
DeclareTimer(const std::string& name, bool open);
|
||||
DeclareTimer(const std::string& name);
|
||||
|
||||
// convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer)
|
||||
operator NamedTimer::FrameState&() { return mNamedTimer.getFrameStateFast(); }
|
||||
private:
|
||||
NamedTimer& mNamedTimer;
|
||||
};
|
||||
|
||||
static DeclareTimer FTM_ARRANGE;
|
||||
static DeclareTimer FTM_ATTACHMENT_UPDATE;
|
||||
static DeclareTimer FTM_AUDIO_UPDATE;
|
||||
static DeclareTimer FTM_AUTO_SELECT;
|
||||
static DeclareTimer FTM_AVATAR_UPDATE;
|
||||
static DeclareTimer FTM_CLEANUP;
|
||||
static DeclareTimer FTM_CLIENT_COPY;
|
||||
static DeclareTimer FTM_CREATE_OBJECT;
|
||||
static DeclareTimer FTM_CULL;
|
||||
static DeclareTimer FTM_CULL_REBOUND;
|
||||
static DeclareTimer FTM_FILTER;
|
||||
static DeclareTimer FTM_FLEXIBLE_UPDATE;
|
||||
static DeclareTimer FTM_FRAME;
|
||||
static DeclareTimer FTM_FRUSTUM_CULL;
|
||||
static DeclareTimer FTM_GEN_FLEX;
|
||||
static DeclareTimer FTM_GEN_TRIANGLES;
|
||||
static DeclareTimer FTM_GEN_VOLUME;
|
||||
static DeclareTimer FTM_GEO_SKY;
|
||||
static DeclareTimer FTM_GEO_UPDATE;
|
||||
static DeclareTimer FTM_HUD_EFFECTS;
|
||||
static DeclareTimer FTM_HUD_UPDATE;
|
||||
static DeclareTimer FTM_IDLE;
|
||||
static DeclareTimer FTM_IDLE_CB;
|
||||
static DeclareTimer FTM_IDLE_NETWORK;
|
||||
static DeclareTimer FTM_IMAGE_CREATE;
|
||||
static DeclareTimer FTM_IMAGE_MARK_DIRTY;
|
||||
static DeclareTimer FTM_IMAGE_UPDATE;
|
||||
static DeclareTimer FTM_INVENTORY;
|
||||
static DeclareTimer FTM_JOINT_UPDATE;
|
||||
static DeclareTimer FTM_KEYHANDLER;
|
||||
static DeclareTimer FTM_LOAD_AVATAR;
|
||||
static DeclareTimer FTM_LOD_UPDATE;
|
||||
static DeclareTimer FTM_MESSAGES;
|
||||
static DeclareTimer FTM_MOUSEHANDLER;
|
||||
static DeclareTimer FTM_NETWORK;
|
||||
static DeclareTimer FTM_OBJECTLIST_UPDATE;
|
||||
static DeclareTimer FTM_OCCLUSION_READBACK;
|
||||
static DeclareTimer FTM_OCTREE_BALANCE;
|
||||
static DeclareTimer FTM_PICK;
|
||||
static DeclareTimer FTM_PIPELINE;
|
||||
static DeclareTimer FTM_POOLRENDER;
|
||||
static DeclareTimer FTM_POOLS;
|
||||
static DeclareTimer FTM_PROCESS_IMAGES;
|
||||
static DeclareTimer FTM_PROCESS_MESSAGES;
|
||||
static DeclareTimer FTM_PROCESS_OBJECTS;
|
||||
static DeclareTimer FTM_PUMP;
|
||||
static DeclareTimer FTM_REBUILD_GRASS_VB;
|
||||
static DeclareTimer FTM_REBUILD_PARTICLE_VB;
|
||||
static DeclareTimer FTM_REBUILD_TERRAIN_VB;
|
||||
static DeclareTimer FTM_REBUILD_VBO;
|
||||
static DeclareTimer FTM_REBUILD_VOLUME_VB;
|
||||
static DeclareTimer FTM_REFRESH;
|
||||
static DeclareTimer FTM_REGION_UPDATE;
|
||||
static DeclareTimer FTM_RENDER;
|
||||
static DeclareTimer FTM_RENDER_ALPHA;
|
||||
static DeclareTimer FTM_RENDER_BLOOM;
|
||||
static DeclareTimer FTM_RENDER_BLOOM_FBO;
|
||||
static DeclareTimer FTM_RENDER_BUMP;
|
||||
static DeclareTimer FTM_RENDER_CHARACTERS;
|
||||
static DeclareTimer FTM_RENDER_FAKE_VBO_UPDATE;
|
||||
static DeclareTimer FTM_RENDER_FONTS;
|
||||
static DeclareTimer FTM_RENDER_FULLBRIGHT;
|
||||
static DeclareTimer FTM_RENDER_GEOMETRY;
|
||||
static DeclareTimer FTM_RENDER_GLOW;
|
||||
static DeclareTimer FTM_RENDER_GRASS;
|
||||
static DeclareTimer FTM_RENDER_INVISIBLE;
|
||||
static DeclareTimer FTM_RENDER_OCCLUSION;
|
||||
static DeclareTimer FTM_RENDER_SHINY;
|
||||
static DeclareTimer FTM_RENDER_SIMPLE;
|
||||
static DeclareTimer FTM_RENDER_TERRAIN;
|
||||
static DeclareTimer FTM_RENDER_TREES;
|
||||
static DeclareTimer FTM_RENDER_UI;
|
||||
static DeclareTimer FTM_RENDER_WATER;
|
||||
static DeclareTimer FTM_RENDER_WL_SKY;
|
||||
static DeclareTimer FTM_RESET_DRAWORDER;
|
||||
static DeclareTimer FTM_SHADOW_ALPHA;
|
||||
static DeclareTimer FTM_SHADOW_AVATAR;
|
||||
static DeclareTimer FTM_SHADOW_RENDER;
|
||||
static DeclareTimer FTM_SHADOW_SIMPLE;
|
||||
static DeclareTimer FTM_SHADOW_TERRAIN;
|
||||
static DeclareTimer FTM_SHADOW_TREE;
|
||||
static DeclareTimer FTM_SIMULATE_PARTICLES;
|
||||
static DeclareTimer FTM_SLEEP;
|
||||
static DeclareTimer FTM_SORT;
|
||||
static DeclareTimer FTM_STATESORT;
|
||||
static DeclareTimer FTM_STATESORT_DRAWABLE;
|
||||
static DeclareTimer FTM_STATESORT_POSTSORT;
|
||||
static DeclareTimer FTM_SWAP;
|
||||
static DeclareTimer FTM_TEMP1;
|
||||
static DeclareTimer FTM_TEMP2;
|
||||
static DeclareTimer FTM_TEMP3;
|
||||
static DeclareTimer FTM_TEMP4;
|
||||
static DeclareTimer FTM_TEMP5;
|
||||
static DeclareTimer FTM_TEMP6;
|
||||
static DeclareTimer FTM_TEMP7;
|
||||
static DeclareTimer FTM_TEMP8;
|
||||
static DeclareTimer FTM_UPDATE_ANIMATION;
|
||||
static DeclareTimer FTM_UPDATE_AVATAR;
|
||||
static DeclareTimer FTM_UPDATE_CLOUDS;
|
||||
static DeclareTimer FTM_UPDATE_GRASS;
|
||||
static DeclareTimer FTM_UPDATE_MOVE;
|
||||
static DeclareTimer FTM_UPDATE_PARTICLES;
|
||||
static DeclareTimer FTM_UPDATE_PRIMITIVES;
|
||||
static DeclareTimer FTM_UPDATE_SKY;
|
||||
static DeclareTimer FTM_UPDATE_TERRAIN;
|
||||
static DeclareTimer FTM_UPDATE_TEXTURES;
|
||||
static DeclareTimer FTM_UPDATE_TREE;
|
||||
static DeclareTimer FTM_UPDATE_WATER;
|
||||
static DeclareTimer FTM_UPDATE_WLPARAM;
|
||||
static DeclareTimer FTM_VFILE_WAIT;
|
||||
static DeclareTimer FTM_WORLD_UPDATE;
|
||||
|
||||
public:
|
||||
static LLFastTimer::EFastTimerType sCurType;
|
||||
enum RootTimerMarker { ROOT };
|
||||
|
||||
static LLMutex* sLogLock;
|
||||
static std::queue<LLSD> sLogQueue;
|
||||
static BOOL sLog;
|
||||
static BOOL sMetricLog;
|
||||
|
||||
LLFastTimer(EFastTimerType type)
|
||||
LLFastTimer(RootTimerMarker);
|
||||
|
||||
LLFastTimer(NamedTimer::FrameState& timer)
|
||||
: mFrameState(&timer)
|
||||
{
|
||||
#if FAST_TIMER_ON
|
||||
mType = type;
|
||||
sCurType = type;
|
||||
// These don't get counted, because they use CPU clockticks
|
||||
//gTimerBins[gCurTimerBin]++;
|
||||
//LLTimer::sNumTimerCalls++;
|
||||
NamedTimer::FrameState* frame_state = mFrameState;
|
||||
frame_state->mLastStartTime = get_cpu_clock_count();
|
||||
mStartSelfTime = frame_state->mLastStartTime;
|
||||
|
||||
U64 cpu_clocks = get_cpu_clock_count();
|
||||
frame_state->mActiveCount++;
|
||||
frame_state->mCalls++;
|
||||
// keep current parent as long as it is active when we are
|
||||
frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0);
|
||||
|
||||
mLastTimer = sCurTimer;
|
||||
sCurTimer = this;
|
||||
}
|
||||
|
||||
sStart[sCurDepth] = cpu_clocks;
|
||||
sCurDepth++;
|
||||
#endif
|
||||
};
|
||||
~LLFastTimer()
|
||||
{
|
||||
#if FAST_TIMER_ON
|
||||
U64 end,delta;
|
||||
int i;
|
||||
NamedTimer::FrameState* frame_state = mFrameState;
|
||||
U64 cur_time = get_cpu_clock_count();
|
||||
frame_state->mSelfTimeCounter += cur_time - mStartSelfTime;
|
||||
|
||||
// These don't get counted, because they use CPU clockticks
|
||||
//gTimerBins[gCurTimerBin]++;
|
||||
//LLTimer::sNumTimerCalls++;
|
||||
end = get_cpu_clock_count();
|
||||
frame_state->mActiveCount--;
|
||||
LLFastTimer* last_timer = mLastTimer;
|
||||
sCurTimer = last_timer;
|
||||
|
||||
sCurDepth--;
|
||||
delta = end - sStart[sCurDepth];
|
||||
sCounter[mType] += delta;
|
||||
sCalls[mType]++;
|
||||
// Subtract delta from parents
|
||||
for (i=0; i<sCurDepth; i++)
|
||||
sStart[i] += delta;
|
||||
// store last caller to bootstrap tree creation
|
||||
frame_state->mLastCaller = last_timer->mFrameState;
|
||||
|
||||
// we are only tracking self time, so subtract our total time delta from parents
|
||||
U64 total_time = cur_time - frame_state->mLastStartTime;
|
||||
last_timer->mStartSelfTime += total_time;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// call this once a frame to reset timers
|
||||
static void nextFrame();
|
||||
|
||||
// call this to reset timer hierarchy, averages, etc.
|
||||
static void reset();
|
||||
|
||||
static U64 countsPerSecond();
|
||||
static S32 getLastFrameIndex() { return sLastFrameIndex; }
|
||||
static S32 getCurFrameIndex() { return sCurFrameIndex; }
|
||||
|
||||
static void writeLog(std::ostream& os);
|
||||
|
||||
public:
|
||||
static int sCurDepth;
|
||||
static U64 sStart[FTM_MAX_DEPTH];
|
||||
static U64 sCounter[FTM_NUM_TYPES];
|
||||
static U64 sCalls[FTM_NUM_TYPES];
|
||||
static U64 sCountAverage[FTM_NUM_TYPES];
|
||||
static U64 sCallAverage[FTM_NUM_TYPES];
|
||||
static U64 sCountHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES];
|
||||
static U64 sCallHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES];
|
||||
static S32 sCurFrameIndex;
|
||||
static S32 sLastFrameIndex;
|
||||
static int sPauseHistory;
|
||||
static int sResetHistory;
|
||||
static F64 sCPUClockFrequency;
|
||||
static bool sPauseHistory;
|
||||
static bool sResetHistory;
|
||||
|
||||
private:
|
||||
EFastTimerType mType;
|
||||
typedef std::vector<LLFastTimer*> timer_stack_t;
|
||||
static LLFastTimer* sCurTimer;
|
||||
static S32 sCurFrameIndex;
|
||||
static S32 sLastFrameIndex;
|
||||
|
||||
static F64 sCPUClockFrequency;
|
||||
U64 mStartSelfTime; // start time + time of all child timers
|
||||
NamedTimer::FrameState* mFrameState;
|
||||
LLFastTimer* mLastTimer;
|
||||
};
|
||||
|
||||
|
||||
#endif // LL_LLFASTTIMER_H
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
// This mix-in class adds support for tracking all instances of the specified class parameter T
|
||||
// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
|
||||
// If KEY is not provided, then instances are stored in a simple set
|
||||
// *NOTE: see explicit specialization below for default KEY==T* case
|
||||
template<typename T, typename KEY = T*>
|
||||
class LLInstanceTracker : boost::noncopyable
|
||||
{
|
||||
|
|
@ -83,6 +84,8 @@ private:
|
|||
static std::map<KEY, T*>* sInstances;
|
||||
};
|
||||
|
||||
// explicit specialization for default case where KEY is T*
|
||||
// use a simple std::set<T*>
|
||||
template<typename T>
|
||||
class LLInstanceTracker<T, T*>
|
||||
{
|
||||
|
|
@ -90,8 +93,8 @@ public:
|
|||
typedef typename std::set<T*>::iterator instance_iter;
|
||||
typedef typename std::set<T*>::const_iterator instance_const_iter;
|
||||
|
||||
static instance_iter instancesBegin() { return getSet().begin(); }
|
||||
static instance_iter instancesEnd() { return getSet().end(); }
|
||||
static instance_iter beginInstances() { return getSet().begin(); }
|
||||
static instance_iter endInstances() { return getSet().end(); }
|
||||
static S32 instanceCount() { return getSet().size(); }
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -38,9 +38,12 @@
|
|||
#include "llsd.h"
|
||||
#include "llsdserialize.h"
|
||||
|
||||
LLLiveAppConfig::LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period)
|
||||
: LLLiveFile(filename, refresh_period),
|
||||
mApp(app)
|
||||
LLLiveAppConfig::LLLiveAppConfig(
|
||||
const std::string& filename,
|
||||
F32 refresh_period,
|
||||
LLApp::OptionPriority priority) :
|
||||
LLLiveFile(filename, refresh_period),
|
||||
mPriority(priority)
|
||||
{ }
|
||||
|
||||
|
||||
|
|
@ -48,7 +51,7 @@ LLLiveAppConfig::~LLLiveAppConfig()
|
|||
{ }
|
||||
|
||||
// virtual
|
||||
void LLLiveAppConfig::loadFile()
|
||||
bool LLLiveAppConfig::loadFile()
|
||||
{
|
||||
llinfos << "LLLiveAppConfig::loadFile(): reading from "
|
||||
<< filename() << llendl;
|
||||
|
|
@ -59,12 +62,25 @@ void LLLiveAppConfig::loadFile()
|
|||
LLSDSerialize::fromXML(config, file);
|
||||
if(!config.isMap())
|
||||
{
|
||||
llinfos << "LLDataserverConfig::loadFile(): not an map!"
|
||||
llwarns << "Live app config not an map in " << filename()
|
||||
<< " Ignoring the data." << llendl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
mApp->setOptionData(
|
||||
LLApp::PRIORITY_SPECIFIC_CONFIGURATION, config);
|
||||
else
|
||||
{
|
||||
llinfos << "Live file " << filename() << " does not exit." << llendl;
|
||||
}
|
||||
// *NOTE: we do not handle the else case here because we would not
|
||||
// have attempted to load the file unless LLLiveFile had
|
||||
// determined there was a reason to load it. This only happens
|
||||
// when either the file has been updated or it is either suddenly
|
||||
// in existence or has passed out of existence. Therefore, we want
|
||||
// to set the config to an empty config, and return that it
|
||||
// changed.
|
||||
|
||||
LLApp* app = LLApp::instance();
|
||||
if(app) app->setOptionData(mPriority, config);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,25 +33,43 @@
|
|||
#ifndef LLLIVEAPPCONFIG_H
|
||||
#define LLLIVEAPPCONFIG_H
|
||||
|
||||
#include "llapp.h"
|
||||
#include "lllivefile.h"
|
||||
|
||||
class LLApp;
|
||||
|
||||
class LL_COMMON_API LLLiveAppConfig : public LLLiveFile
|
||||
/**
|
||||
* @class LLLiveAppConfig
|
||||
* @see LLLiveFile
|
||||
*
|
||||
* To use this, instantiate a LLLiveAppConfig object inside your main
|
||||
* loop. The traditional name for it is live_config. Be sure to call
|
||||
* <code>live_config.checkAndReload()</code> periodically.
|
||||
*/
|
||||
class LLLiveAppConfig : public LLLiveFile
|
||||
{
|
||||
public:
|
||||
// To use this, instantiate a LLLiveAppConfig object inside your main loop.
|
||||
// The traditional name for it is live_config.
|
||||
// Be sure to call live_config.checkAndReload() periodically.
|
||||
|
||||
LLLiveAppConfig(LLApp* app, const std::string& filename, F32 refresh_period);
|
||||
~LLLiveAppConfig();
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param filename. The name of the file for periodically checking
|
||||
* configuration.
|
||||
* @param refresh_period How often the internal timer should
|
||||
* bother checking the filesystem.
|
||||
* @param The application priority level of that configuration file.
|
||||
*/
|
||||
LLLiveAppConfig(
|
||||
const std::string& filename,
|
||||
F32 refresh_period,
|
||||
LLApp::OptionPriority priority);
|
||||
|
||||
~LLLiveAppConfig(); ///< Destructor
|
||||
|
||||
protected:
|
||||
/*virtual*/ void loadFile();
|
||||
/*virtual*/ bool loadFile();
|
||||
|
||||
private:
|
||||
LLApp* mApp;
|
||||
LLApp::OptionPriority mPriority;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -35,14 +35,17 @@
|
|||
#include "llframetimer.h"
|
||||
#include "lltimer.h"
|
||||
|
||||
const F32 DEFAULT_CONFIG_FILE_REFRESH = 5.0f;
|
||||
|
||||
|
||||
class LLLiveFile::Impl
|
||||
{
|
||||
public:
|
||||
Impl(const std::string &filename, const F32 refresh_period);
|
||||
Impl(const std::string& filename, const F32 refresh_period);
|
||||
~Impl();
|
||||
|
||||
bool check();
|
||||
|
||||
void changed();
|
||||
|
||||
bool mForceCheck;
|
||||
F32 mRefreshPeriod;
|
||||
|
|
@ -50,16 +53,19 @@ public:
|
|||
|
||||
std::string mFilename;
|
||||
time_t mLastModTime;
|
||||
time_t mLastStatTime;
|
||||
bool mLastExists;
|
||||
|
||||
LLEventTimer* mEventTimer;
|
||||
};
|
||||
|
||||
LLLiveFile::Impl::Impl(const std::string &filename, const F32 refresh_period)
|
||||
: mForceCheck(true),
|
||||
LLLiveFile::Impl::Impl(const std::string& filename, const F32 refresh_period)
|
||||
:
|
||||
mForceCheck(true),
|
||||
mRefreshPeriod(refresh_period),
|
||||
mFilename(filename),
|
||||
mLastModTime(0),
|
||||
mLastStatTime(0),
|
||||
mLastExists(false),
|
||||
mEventTimer(NULL)
|
||||
{
|
||||
|
|
@ -70,7 +76,7 @@ LLLiveFile::Impl::~Impl()
|
|||
delete mEventTimer;
|
||||
}
|
||||
|
||||
LLLiveFile::LLLiveFile(const std::string &filename, const F32 refresh_period)
|
||||
LLLiveFile::LLLiveFile(const std::string& filename, const F32 refresh_period)
|
||||
: impl(* new Impl(filename, refresh_period))
|
||||
{
|
||||
}
|
||||
|
|
@ -121,17 +127,30 @@ bool LLLiveFile::Impl::check()
|
|||
|
||||
// We want to read the file. Update status info for the file.
|
||||
mLastExists = true;
|
||||
mLastModTime = stat_data.st_mtime;
|
||||
|
||||
mLastStatTime = stat_data.st_mtime;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLLiveFile::Impl::changed()
|
||||
{
|
||||
// we wanted to read this file, and we were successful.
|
||||
mLastModTime = mLastStatTime;
|
||||
}
|
||||
|
||||
bool LLLiveFile::checkAndReload()
|
||||
{
|
||||
bool changed = impl.check();
|
||||
if (changed)
|
||||
{
|
||||
loadFile();
|
||||
if(loadFile())
|
||||
{
|
||||
impl.changed();
|
||||
this->changed();
|
||||
}
|
||||
else
|
||||
{
|
||||
changed = false;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,29 +33,65 @@
|
|||
#ifndef LL_LLLIVEFILE_H
|
||||
#define LL_LLLIVEFILE_H
|
||||
|
||||
const F32 configFileRefreshRate = 5.0; // seconds
|
||||
extern const F32 DEFAULT_CONFIG_FILE_REFRESH;
|
||||
|
||||
|
||||
class LL_COMMON_API LLLiveFile
|
||||
{
|
||||
public:
|
||||
LLLiveFile(const std::string &filename, const F32 refresh_period = 5.f);
|
||||
LLLiveFile(const std::string& filename, const F32 refresh_period = 5.f);
|
||||
virtual ~LLLiveFile();
|
||||
|
||||
/**
|
||||
* @brief Check to see if this live file should reload.
|
||||
*
|
||||
* Call this before using anything that was read & cached
|
||||
* from the file.
|
||||
*
|
||||
* This method calls the <code>loadFile()</code> method if
|
||||
* any of:
|
||||
* file has a new modify time since the last check
|
||||
* file used to exist and now does not
|
||||
* file used to not exist but now does
|
||||
* @return Returns true if the file was reloaded.
|
||||
*/
|
||||
bool checkAndReload();
|
||||
// Returns true if the file changed in any way
|
||||
// Call this before using anything that was read & cached from the file
|
||||
|
||||
|
||||
std::string filename() const;
|
||||
|
||||
/**
|
||||
* @brief Add this live file to an automated recheck.
|
||||
*
|
||||
* Normally, just calling checkAndReload() is enough. In some
|
||||
* cases though, you may need to let the live file periodically
|
||||
* check itself.
|
||||
*/
|
||||
void addToEventTimer();
|
||||
// Normally, just calling checkAndReload() is enough. In some cases
|
||||
// though, you may need to let the live file periodically check itself.
|
||||
|
||||
void setRefreshPeriod(F32 seconds);
|
||||
|
||||
protected:
|
||||
virtual void loadFile() = 0; // Implement this to load your file if it changed
|
||||
/**
|
||||
* @breif Implement this to load your file if it changed.
|
||||
*
|
||||
* This method is called automatically by <code>checkAndReload()</code>,
|
||||
* so though you must implement this in derived classes, you do
|
||||
* not need to call it manually.
|
||||
* @return Returns true if the file was successfully loaded.
|
||||
*/
|
||||
virtual bool loadFile() = 0;
|
||||
|
||||
/**
|
||||
* @brief Implement this method if you want to get a change callback.
|
||||
*
|
||||
* This virtual function will be called automatically at the end
|
||||
* of <code>checkAndReload()</code> if a new configuration was
|
||||
* loaded. This does not track differences between the current and
|
||||
* newly loaded file, so any successful load event will trigger a
|
||||
* <code>changed()</code> callback. Default is to do nothing.
|
||||
*/
|
||||
virtual void changed() {}
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
#endif
|
||||
|
||||
#include "llmemory.h"
|
||||
#include "llmemtype.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -74,162 +73,6 @@ void LLMemory::freeReserve()
|
|||
reserveMem = NULL;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//static
|
||||
#if MEM_TRACK_TYPE
|
||||
S32 LLMemType::sCurDepth = 0;
|
||||
S32 LLMemType::sCurType = LLMemType::MTYPE_INIT;
|
||||
S32 LLMemType::sType[LLMemType::MTYPE_MAX_DEPTH];
|
||||
S32 LLMemType::sMemCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
|
||||
S32 LLMemType::sMaxMemCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
|
||||
S32 LLMemType::sNewCount[LLMemType::MTYPE_NUM_TYPES] = { 0 };
|
||||
S32 LLMemType::sOverheadMem = 0;
|
||||
|
||||
const char* LLMemType::sTypeDesc[LLMemType::MTYPE_NUM_TYPES] =
|
||||
{
|
||||
"INIT",
|
||||
"STARTUP",
|
||||
"MAIN",
|
||||
|
||||
"IMAGEBASE",
|
||||
"IMAGERAW",
|
||||
"IMAGEFORMATTED",
|
||||
|
||||
"APPFMTIMAGE",
|
||||
"APPRAWIMAGE",
|
||||
"APPAUXRAWIMAGE",
|
||||
|
||||
"DRAWABLE",
|
||||
"OBJECT",
|
||||
"PIPELINE",
|
||||
"AVATAR",
|
||||
"PARTICLES",
|
||||
"REGIONS",
|
||||
"INVENTORY",
|
||||
"ANIMATION",
|
||||
"NETWORK",
|
||||
"PHYSICS",
|
||||
"INTERESTLIST",
|
||||
|
||||
"SCRIPT",
|
||||
"SCRIPT_RUN",
|
||||
"SCRIPT_BYTECODE",
|
||||
|
||||
"IO_PUMP",
|
||||
"IO_TCP",
|
||||
"IO_BUFFER",
|
||||
"IO_HTTP_SERVER"
|
||||
"IO_SD_SERVER",
|
||||
"IO_SD_CLIENT",
|
||||
"IO_URL_REQUEST",
|
||||
|
||||
"TEMP1",
|
||||
"TEMP2",
|
||||
"TEMP3",
|
||||
"TEMP4",
|
||||
"TEMP5",
|
||||
"TEMP6",
|
||||
"TEMP7",
|
||||
"TEMP8",
|
||||
"TEMP9"
|
||||
};
|
||||
|
||||
#endif
|
||||
S32 LLMemType::sTotalMem = 0;
|
||||
S32 LLMemType::sMaxTotalMem = 0;
|
||||
|
||||
//static
|
||||
void LLMemType::printMem()
|
||||
{
|
||||
S32 misc_mem = sTotalMem;
|
||||
#if MEM_TRACK_TYPE
|
||||
for (S32 i=0; i<MTYPE_NUM_TYPES; i++)
|
||||
{
|
||||
if (sMemCount[i])
|
||||
{
|
||||
llinfos << llformat("MEM: % 20s %03d MB (%03d MB) in %06d News",sTypeDesc[i],sMemCount[i]>>20,sMaxMemCount[i]>>20, sNewCount[i]) << llendl;
|
||||
}
|
||||
misc_mem -= sMemCount[i];
|
||||
}
|
||||
#endif
|
||||
llinfos << llformat("MEM: % 20s %03d MB","MISC",misc_mem>>20) << llendl;
|
||||
llinfos << llformat("MEM: % 20s %03d MB (Max=%d MB)","TOTAL",sTotalMem>>20,sMaxTotalMem>>20) << llendl;
|
||||
}
|
||||
|
||||
#if MEM_TRACK_MEM
|
||||
|
||||
void* ll_allocate (size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
{
|
||||
llwarns << "Null allocation" << llendl;
|
||||
}
|
||||
|
||||
size = (size+3)&~3;
|
||||
S32 alloc_size = size + 4;
|
||||
#if MEM_TRACK_TYPE
|
||||
alloc_size += 4;
|
||||
#endif
|
||||
char* p = (char*)malloc(alloc_size);
|
||||
if (p == NULL)
|
||||
{
|
||||
LLMemory::freeReserve();
|
||||
llerrs << "Out of memory Error" << llendl;
|
||||
}
|
||||
LLMemType::sTotalMem += size;
|
||||
LLMemType::sMaxTotalMem = llmax(LLMemType::sTotalMem, LLMemType::sMaxTotalMem);
|
||||
LLMemType::sOverheadMem += 4;
|
||||
*(size_t*)p = size;
|
||||
p += 4;
|
||||
#if MEM_TRACK_TYPE
|
||||
if (LLMemType::sCurType < 0 || LLMemType::sCurType >= LLMemType::MTYPE_NUM_TYPES)
|
||||
{
|
||||
llerrs << "Memory Type Error: new" << llendl;
|
||||
}
|
||||
LLMemType::sOverheadMem += 4;
|
||||
*(S32*)p = LLMemType::sCurType;
|
||||
p += 4;
|
||||
LLMemType::sMemCount[LLMemType::sCurType] += size;
|
||||
if (LLMemType::sMemCount[LLMemType::sCurType] > LLMemType::sMaxMemCount[LLMemType::sCurType])
|
||||
{
|
||||
LLMemType::sMaxMemCount[LLMemType::sCurType] = LLMemType::sMemCount[LLMemType::sCurType];
|
||||
}
|
||||
LLMemType::sNewCount[LLMemType::sCurType]++;
|
||||
#endif
|
||||
return (void*)p;
|
||||
}
|
||||
|
||||
void ll_release (void *pin)
|
||||
{
|
||||
if (!pin)
|
||||
{
|
||||
return;
|
||||
}
|
||||
char* p = (char*)pin;
|
||||
#if MEM_TRACK_TYPE
|
||||
p -= 4;
|
||||
S32 type = *(S32*)p;
|
||||
if (type < 0 || type >= LLMemType::MTYPE_NUM_TYPES)
|
||||
{
|
||||
llerrs << "Memory Type Error: delete" << llendl;
|
||||
}
|
||||
#endif
|
||||
p -= 4;
|
||||
S32 size = *(size_t*)p;
|
||||
LLMemType::sOverheadMem -= 4;
|
||||
#if MEM_TRACK_TYPE
|
||||
LLMemType::sMemCount[type] -= size;
|
||||
LLMemType::sOverheadMem -= 4;
|
||||
LLMemType::sNewCount[type]--;
|
||||
#endif
|
||||
LLMemType::sTotalMem -= size;
|
||||
free(p);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void* ll_allocate (size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
|
|
@ -250,32 +93,6 @@ void ll_release (void *p)
|
|||
free(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if MEM_TRACK_MEM
|
||||
|
||||
void* operator new (size_t size)
|
||||
{
|
||||
return ll_allocate(size);
|
||||
}
|
||||
|
||||
void* operator new[] (size_t size)
|
||||
{
|
||||
return ll_allocate(size);
|
||||
}
|
||||
|
||||
void operator delete (void *p)
|
||||
{
|
||||
ll_release(p);
|
||||
}
|
||||
|
||||
void operator delete[] (void *p)
|
||||
{
|
||||
ll_release(p);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
|
|
|
|||
|
|
@ -38,7 +38,10 @@ extern S32 gTotalDAlloc;
|
|||
extern S32 gTotalDAUse;
|
||||
extern S32 gDACount;
|
||||
|
||||
class LL_COMMON_API LLMemory
|
||||
extern void* ll_allocate (size_t size);
|
||||
extern void ll_release (void *p);
|
||||
|
||||
class LLMemory
|
||||
{
|
||||
public:
|
||||
static void initClass();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,237 @@
|
|||
/**
|
||||
* @file llmemtype.cpp
|
||||
* @brief Simple memory allocation/deallocation tracking stuff here
|
||||
*
|
||||
* $LicenseInfo:firstyear=2002&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2002-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llmemtype.h"
|
||||
#include "llallocator.h"
|
||||
|
||||
std::vector<char const *> LLMemType::DeclareMemType::mNameList;
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INIT("Init");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_STARTUP("Startup");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_MAIN("Main");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_FRAME("Frame");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_GATHER_INPUT("GatherInput");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_JOY_KEY("JoyKey");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE("Idle");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_PUMP("IdlePump");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_NETWORK("IdleNetwork");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_REGIONS("IdleUpdateRegions");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION("IdleUpdateViewerRegion");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_SURFACE("IdleUpdateSurface");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_PARCEL_OVERLAY("IdleUpdateParcelOverlay");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_AUDIO("IdleAudio");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING("CacheProcessPending");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS("CacheProcessPendingAsks");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING_REPLIES("CacheProcessPendingReplies");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_MESSAGE_CHECK_ALL("MessageCheckAll");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_MESSAGE_PROCESS_ACKS("MessageProcessAcks");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_RENDER("Render");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_SLEEP("Sleep");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_NETWORK("Network");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PHYSICS("Physics");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INTERESTLIST("InterestList");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IMAGEBASE("ImageBase");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IMAGERAW("ImageRaw");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IMAGEFORMATTED("ImageFormatted");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_APPFMTIMAGE("AppFmtImage");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_APPRAWIMAGE("AppRawImage");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_APPAUXRAWIMAGE("AppAuxRawImage");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DRAWABLE("Drawable");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT("Object");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT_PROCESS_UPDATE("ObjectProcessUpdate");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT_PROCESS_UPDATE_CORE("ObjectProcessUpdateCore");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY("Display");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE("DisplayUpdate");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA("DisplayUpdateCam");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_GEOM("DisplayUpdateGeom");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_SWAP("DisplaySwap");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_HUD("DisplayUpdateHud");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_GEN_REFLECTION("DisplayGenRefl");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE("DisplayImageUpdate");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_STATE_SORT("DisplayStateSort");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_SKY("DisplaySky");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_GEOM("DisplayRenderGeom");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_FLUSH("DisplayRenderFlush");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_UI("DisplayRenderUI");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS("DisplayRenderAttach");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DATA("VertexData");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CONSTRUCTOR("VertexConstr");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTRUCTOR("VertexDestr");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CREATE_VERTICES("VertexCreateVerts");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CREATE_INDICES("VertexCreateIndices");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTROY_BUFFER("VertexDestroyBuff");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTROY_INDICES("VertexDestroyIndices");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UPDATE_VERTS("VertexUpdateVerts");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UPDATE_INDICES("VertexUpdateIndices");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER("VertexAllocateBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_RESIZE_BUFFER("VertexResizeBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER("VertexMapBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES("VertexMapBufferVerts");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES("VertexMapBufferIndices");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UNMAP_BUFFER("VertexUnmapBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SET_STRIDE("VertexSetStride");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SET_BUFFER("VertexSetBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER("VertexSetupVertBuff");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CLEANUP_CLASS("VertexCleanupClass");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_SPACE_PARTITION("SpacePartition");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE("Pipeline");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_INIT("PipelineInit");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS("PipelineCreateBuffs");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RESTORE_GL("PipelineRestroGL");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS("PipelineUnloadShaders");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL("PipelineLightingDetail");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE("PipelineGetPoolType");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ADD_POOL("PipelineAddPool");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE("PipelineAllocDrawable");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ADD_OBJECT("PipelineAddObj");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS("PipelineCreateObjs");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_MOVE("PipelineUpdateMove");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_GEOM("PipelineUpdateGeom");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_VISIBLE("PipelineMarkVisible");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_MOVED("PipelineMarkMoved");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_SHIFT("PipelineMarkShift");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS("PipelineShiftObjs");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_TEXTURED("PipelineMarkTextured");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_REBUILD("PipelineMarkRebuild");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_CULL("PipelineUpdateCull");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_STATE_SORT("PipelineStateSort");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_POST_SORT("PipelinePostSort");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS("PipelineHudEls");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_HL("PipelineRenderHL");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM("PipelineRenderGeom");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED("PipelineRenderGeomDef");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF("PipelineRenderGeomPostDef");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW("PipelineRenderGeomShadow");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_SELECT("PipelineRenderSelect");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_REBUILD_POOLS("PipelineRebuildPools");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP("PipelineQuickLookup");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS("PipelineRenderObjs");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR("PipelineGenImpostors");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_BLOOM("PipelineRenderBloom");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_UPKEEP_POOLS("UpkeepPools");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_AVATAR("Avatar");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_AVATAR_MESH("AvatarMesh");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PARTICLES("Particles");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_REGIONS("Regions");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY("Inventory");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_DRAW("InventoryDraw");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS("InventoryBuildNewViews");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_DO_FOLDER("InventoryDoFolder");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_POST_BUILD("InventoryPostBuild");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_FROM_XML("InventoryFromXML");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_CREATE_NEW_ITEM("InventoryCreateNewItem");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_INIT("InventoryViewInit");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_SHOW("InventoryViewShow");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE("InventoryViewToggle");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_ANIMATION("Animation");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_VOLUME("Volume");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_PRIMITIVE("Primitive");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT("Script");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT_RUN("ScriptRun");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT_BYTECODE("ScriptByteCode");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_PUMP("IoPump");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_TCP("IoTCP");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_BUFFER("IoBuffer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_HTTP_SERVER("IoHttpServer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_SD_SERVER("IoSDServer");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_SD_CLIENT("IoSDClient");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_IO_URL_REQUEST("IOUrlRequest");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_DIRECTX_INIT("DirectXInit");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP1("Temp1");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP2("Temp2");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP3("Temp3");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP4("Temp4");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP5("Temp5");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP6("Temp6");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP7("Temp7");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP8("Temp8");
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_TEMP9("Temp9");
|
||||
|
||||
LLMemType::DeclareMemType LLMemType::MTYPE_OTHER("Other");
|
||||
|
||||
|
||||
LLMemType::DeclareMemType::DeclareMemType(char const * st)
|
||||
{
|
||||
mID = (S32)mNameList.size();
|
||||
mName = st;
|
||||
|
||||
mNameList.push_back(mName);
|
||||
}
|
||||
|
||||
LLMemType::DeclareMemType::~DeclareMemType()
|
||||
{
|
||||
}
|
||||
|
||||
LLMemType::LLMemType(LLMemType::DeclareMemType& dt)
|
||||
{
|
||||
mTypeIndex = dt.mID;
|
||||
LLAllocator::pushMemType(dt.mID);
|
||||
}
|
||||
|
||||
LLMemType::~LLMemType()
|
||||
{
|
||||
LLAllocator::popMemType();
|
||||
}
|
||||
|
||||
char const * LLMemType::getNameFromID(S32 id)
|
||||
{
|
||||
if (id < 0 || id >= (S32)DeclareMemType::mNameList.size())
|
||||
{
|
||||
return "INVALID";
|
||||
}
|
||||
|
||||
return DeclareMemType::mNameList[id];
|
||||
}
|
||||
|
||||
|
|
@ -36,131 +36,210 @@
|
|||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class LLMemType;
|
||||
|
||||
extern void* ll_allocate (size_t size);
|
||||
extern void ll_release (void *p);
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "linden_common.h"
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// WARNING: Never commit with MEM_TRACK_MEM == 1
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
#define MEM_TRACK_MEM (0 && LL_WINDOWS)
|
||||
#define MEM_TRACK_TYPE (1 && MEM_TRACK_MEM)
|
||||
|
||||
#if MEM_TRACK_TYPE
|
||||
#define MEM_DUMP_DATA 1
|
||||
#define MEM_TYPE_NEW(T) \
|
||||
static void* operator new(size_t s) { LLMemType mt(T); return ll_allocate(s); } \
|
||||
static void operator delete(void* p) { ll_release(p); }
|
||||
#include <vector>
|
||||
|
||||
#else
|
||||
#define MEM_TYPE_NEW(T)
|
||||
#endif // MEM_TRACK_TYPE
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class LLMemType
|
||||
{
|
||||
public:
|
||||
// Also update sTypeDesc in llmemory.cpp
|
||||
enum EMemType
|
||||
|
||||
// class we'll initialize all instances of as
|
||||
// static members of MemType. Then use
|
||||
// to construct any new mem type.
|
||||
class DeclareMemType
|
||||
{
|
||||
MTYPE_INIT,
|
||||
MTYPE_STARTUP,
|
||||
MTYPE_MAIN,
|
||||
|
||||
MTYPE_IMAGEBASE,
|
||||
MTYPE_IMAGERAW,
|
||||
MTYPE_IMAGEFORMATTED,
|
||||
public:
|
||||
DeclareMemType(char const * st);
|
||||
~DeclareMemType();
|
||||
|
||||
S32 mID;
|
||||
char const * mName;
|
||||
|
||||
MTYPE_APPFMTIMAGE,
|
||||
MTYPE_APPRAWIMAGE,
|
||||
MTYPE_APPAUXRAWIMAGE,
|
||||
|
||||
MTYPE_DRAWABLE,
|
||||
MTYPE_OBJECT,
|
||||
MTYPE_VERTEX_DATA,
|
||||
MTYPE_SPACE_PARTITION,
|
||||
MTYPE_PIPELINE,
|
||||
MTYPE_AVATAR,
|
||||
MTYPE_AVATAR_MESH,
|
||||
MTYPE_PARTICLES,
|
||||
MTYPE_REGIONS,
|
||||
MTYPE_INVENTORY,
|
||||
MTYPE_ANIMATION,
|
||||
MTYPE_VOLUME,
|
||||
MTYPE_PRIMITIVE,
|
||||
|
||||
MTYPE_NETWORK,
|
||||
MTYPE_PHYSICS,
|
||||
MTYPE_INTERESTLIST,
|
||||
|
||||
MTYPE_SCRIPT,
|
||||
MTYPE_SCRIPT_RUN,
|
||||
MTYPE_SCRIPT_BYTECODE,
|
||||
|
||||
MTYPE_IO_PUMP,
|
||||
MTYPE_IO_TCP,
|
||||
MTYPE_IO_BUFFER,
|
||||
MTYPE_IO_HTTP_SERVER,
|
||||
MTYPE_IO_SD_SERVER,
|
||||
MTYPE_IO_SD_CLIENT,
|
||||
MTYPE_IO_URL_REQUEST,
|
||||
|
||||
MTYPE_TEMP1,
|
||||
MTYPE_TEMP2,
|
||||
MTYPE_TEMP3,
|
||||
MTYPE_TEMP4,
|
||||
MTYPE_TEMP5,
|
||||
MTYPE_TEMP6,
|
||||
MTYPE_TEMP7,
|
||||
MTYPE_TEMP8,
|
||||
MTYPE_TEMP9,
|
||||
|
||||
MTYPE_OTHER, // Special, used by display code
|
||||
|
||||
MTYPE_NUM_TYPES
|
||||
// array so we can map an index ID to Name
|
||||
static std::vector<char const *> mNameList;
|
||||
};
|
||||
enum { MTYPE_MAX_DEPTH = 64 };
|
||||
|
||||
public:
|
||||
LLMemType(EMemType type)
|
||||
{
|
||||
#if MEM_TRACK_TYPE
|
||||
if (type < 0 || type >= MTYPE_NUM_TYPES)
|
||||
llerrs << "LLMemType error" << llendl;
|
||||
if (sCurDepth < 0 || sCurDepth >= MTYPE_MAX_DEPTH)
|
||||
llerrs << "LLMemType error" << llendl;
|
||||
sType[sCurDepth] = sCurType;
|
||||
sCurDepth++;
|
||||
sCurType = type;
|
||||
#endif
|
||||
}
|
||||
~LLMemType()
|
||||
{
|
||||
#if MEM_TRACK_TYPE
|
||||
sCurDepth--;
|
||||
sCurType = sType[sCurDepth];
|
||||
#endif
|
||||
}
|
||||
|
||||
static void reset();
|
||||
static void printMem();
|
||||
LLMemType(DeclareMemType& dt);
|
||||
~LLMemType();
|
||||
|
||||
static char const * getNameFromID(S32 id);
|
||||
|
||||
static DeclareMemType MTYPE_INIT;
|
||||
static DeclareMemType MTYPE_STARTUP;
|
||||
static DeclareMemType MTYPE_MAIN;
|
||||
static DeclareMemType MTYPE_FRAME;
|
||||
|
||||
static DeclareMemType MTYPE_GATHER_INPUT;
|
||||
static DeclareMemType MTYPE_JOY_KEY;
|
||||
|
||||
static DeclareMemType MTYPE_IDLE;
|
||||
static DeclareMemType MTYPE_IDLE_PUMP;
|
||||
static DeclareMemType MTYPE_IDLE_NETWORK;
|
||||
static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS;
|
||||
static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION;
|
||||
static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE;
|
||||
static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY;
|
||||
static DeclareMemType MTYPE_IDLE_AUDIO;
|
||||
|
||||
static DeclareMemType MTYPE_CACHE_PROCESS_PENDING;
|
||||
static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS;
|
||||
static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES;
|
||||
|
||||
static DeclareMemType MTYPE_MESSAGE_CHECK_ALL;
|
||||
static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS;
|
||||
|
||||
static DeclareMemType MTYPE_RENDER;
|
||||
static DeclareMemType MTYPE_SLEEP;
|
||||
|
||||
static DeclareMemType MTYPE_NETWORK;
|
||||
static DeclareMemType MTYPE_PHYSICS;
|
||||
static DeclareMemType MTYPE_INTERESTLIST;
|
||||
|
||||
static DeclareMemType MTYPE_IMAGEBASE;
|
||||
static DeclareMemType MTYPE_IMAGERAW;
|
||||
static DeclareMemType MTYPE_IMAGEFORMATTED;
|
||||
|
||||
public:
|
||||
#if MEM_TRACK_TYPE
|
||||
static S32 sCurDepth;
|
||||
static S32 sCurType;
|
||||
static S32 sType[MTYPE_MAX_DEPTH];
|
||||
static S32 sMemCount[MTYPE_NUM_TYPES];
|
||||
static S32 sMaxMemCount[MTYPE_NUM_TYPES];
|
||||
static S32 sNewCount[MTYPE_NUM_TYPES];
|
||||
static S32 sOverheadMem;
|
||||
static const char* sTypeDesc[MTYPE_NUM_TYPES];
|
||||
#endif
|
||||
static S32 sTotalMem;
|
||||
static S32 sMaxTotalMem;
|
||||
static DeclareMemType MTYPE_APPFMTIMAGE;
|
||||
static DeclareMemType MTYPE_APPRAWIMAGE;
|
||||
static DeclareMemType MTYPE_APPAUXRAWIMAGE;
|
||||
|
||||
static DeclareMemType MTYPE_DRAWABLE;
|
||||
|
||||
static DeclareMemType MTYPE_OBJECT;
|
||||
static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE;
|
||||
static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE;
|
||||
|
||||
static DeclareMemType MTYPE_DISPLAY;
|
||||
static DeclareMemType MTYPE_DISPLAY_UPDATE;
|
||||
static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA;
|
||||
static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM;
|
||||
static DeclareMemType MTYPE_DISPLAY_SWAP;
|
||||
static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD;
|
||||
static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION;
|
||||
static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE;
|
||||
static DeclareMemType MTYPE_DISPLAY_STATE_SORT;
|
||||
static DeclareMemType MTYPE_DISPLAY_SKY;
|
||||
static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM;
|
||||
static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH;
|
||||
static DeclareMemType MTYPE_DISPLAY_RENDER_UI;
|
||||
static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS;
|
||||
|
||||
static DeclareMemType MTYPE_VERTEX_DATA;
|
||||
static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR;
|
||||
static DeclareMemType MTYPE_VERTEX_DESTRUCTOR;
|
||||
static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES;
|
||||
static DeclareMemType MTYPE_VERTEX_CREATE_INDICES;
|
||||
static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES;
|
||||
static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS;
|
||||
static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES;
|
||||
static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_MAP_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES;
|
||||
static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES;
|
||||
static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_SET_STRIDE;
|
||||
static DeclareMemType MTYPE_VERTEX_SET_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER;
|
||||
static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS;
|
||||
|
||||
static DeclareMemType MTYPE_SPACE_PARTITION;
|
||||
|
||||
static DeclareMemType MTYPE_PIPELINE;
|
||||
static DeclareMemType MTYPE_PIPELINE_INIT;
|
||||
static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS;
|
||||
static DeclareMemType MTYPE_PIPELINE_RESTORE_GL;
|
||||
static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS;
|
||||
static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL;
|
||||
static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE;
|
||||
static DeclareMemType MTYPE_PIPELINE_ADD_POOL;
|
||||
static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE;
|
||||
static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT;
|
||||
static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS;
|
||||
static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE;
|
||||
static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM;
|
||||
static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE;
|
||||
static DeclareMemType MTYPE_PIPELINE_MARK_MOVED;
|
||||
static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT;
|
||||
static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS;
|
||||
static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED;
|
||||
static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD;
|
||||
static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL;
|
||||
static DeclareMemType MTYPE_PIPELINE_STATE_SORT;
|
||||
static DeclareMemType MTYPE_PIPELINE_POST_SORT;
|
||||
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_HL;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT;
|
||||
static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS;
|
||||
static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS;
|
||||
static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR;
|
||||
static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM;
|
||||
|
||||
static DeclareMemType MTYPE_UPKEEP_POOLS;
|
||||
|
||||
static DeclareMemType MTYPE_AVATAR;
|
||||
static DeclareMemType MTYPE_AVATAR_MESH;
|
||||
static DeclareMemType MTYPE_PARTICLES;
|
||||
static DeclareMemType MTYPE_REGIONS;
|
||||
|
||||
static DeclareMemType MTYPE_INVENTORY;
|
||||
static DeclareMemType MTYPE_INVENTORY_DRAW;
|
||||
static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS;
|
||||
static DeclareMemType MTYPE_INVENTORY_DO_FOLDER;
|
||||
static DeclareMemType MTYPE_INVENTORY_POST_BUILD;
|
||||
static DeclareMemType MTYPE_INVENTORY_FROM_XML;
|
||||
static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM;
|
||||
static DeclareMemType MTYPE_INVENTORY_VIEW_INIT;
|
||||
static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW;
|
||||
static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE;
|
||||
|
||||
static DeclareMemType MTYPE_ANIMATION;
|
||||
static DeclareMemType MTYPE_VOLUME;
|
||||
static DeclareMemType MTYPE_PRIMITIVE;
|
||||
|
||||
static DeclareMemType MTYPE_SCRIPT;
|
||||
static DeclareMemType MTYPE_SCRIPT_RUN;
|
||||
static DeclareMemType MTYPE_SCRIPT_BYTECODE;
|
||||
|
||||
static DeclareMemType MTYPE_IO_PUMP;
|
||||
static DeclareMemType MTYPE_IO_TCP;
|
||||
static DeclareMemType MTYPE_IO_BUFFER;
|
||||
static DeclareMemType MTYPE_IO_HTTP_SERVER;
|
||||
static DeclareMemType MTYPE_IO_SD_SERVER;
|
||||
static DeclareMemType MTYPE_IO_SD_CLIENT;
|
||||
static DeclareMemType MTYPE_IO_URL_REQUEST;
|
||||
|
||||
static DeclareMemType MTYPE_DIRECTX_INIT;
|
||||
|
||||
static DeclareMemType MTYPE_TEMP1;
|
||||
static DeclareMemType MTYPE_TEMP2;
|
||||
static DeclareMemType MTYPE_TEMP3;
|
||||
static DeclareMemType MTYPE_TEMP4;
|
||||
static DeclareMemType MTYPE_TEMP5;
|
||||
static DeclareMemType MTYPE_TEMP6;
|
||||
static DeclareMemType MTYPE_TEMP7;
|
||||
static DeclareMemType MTYPE_TEMP8;
|
||||
static DeclareMemType MTYPE_TEMP9;
|
||||
|
||||
static DeclareMemType MTYPE_OTHER; // Special; used by display code
|
||||
|
||||
S32 mTypeIndex;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
* @file llstacktrace.cpp
|
||||
* @brief stack tracing functionality
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "llstacktrace.h"
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "windows.h"
|
||||
#include "Dbghelp.h"
|
||||
|
||||
typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
|
||||
IN ULONG frames_to_skip,
|
||||
IN ULONG frames_to_capture,
|
||||
OUT PVOID *backtrace,
|
||||
OUT PULONG backtrace_hash);
|
||||
|
||||
static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
|
||||
(RtlCaptureStackBackTrace_Function*)
|
||||
GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
|
||||
|
||||
bool ll_get_stack_trace(std::vector<std::string>& lines)
|
||||
{
|
||||
const S32 MAX_STACK_DEPTH = 32;
|
||||
const S32 STRING_NAME_LENGTH = 200;
|
||||
const S32 FRAME_SKIP = 2;
|
||||
static BOOL symbolsLoaded = false;
|
||||
static BOOL firstCall = true;
|
||||
|
||||
HANDLE hProc = GetCurrentProcess();
|
||||
|
||||
// load the symbols if they're not loaded
|
||||
if(!symbolsLoaded && firstCall)
|
||||
{
|
||||
symbolsLoaded = SymInitialize(hProc, NULL, true);
|
||||
firstCall = false;
|
||||
}
|
||||
|
||||
// if loaded, get the call stack
|
||||
if(symbolsLoaded)
|
||||
{
|
||||
// create the frames to hold the addresses
|
||||
void* frames[MAX_STACK_DEPTH];
|
||||
memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
|
||||
S32 depth = 0;
|
||||
|
||||
// get the addresses
|
||||
depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);
|
||||
|
||||
IMAGEHLP_LINE64 line;
|
||||
memset(&line, 0, sizeof(IMAGEHLP_LINE64));
|
||||
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||
|
||||
// create something to hold address info
|
||||
PIMAGEHLP_SYMBOL64 pSym;
|
||||
pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
|
||||
memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
|
||||
pSym->MaxNameLength = STRING_NAME_LENGTH;
|
||||
pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
|
||||
|
||||
// get address info for each address frame
|
||||
// and store
|
||||
for(S32 i=0; i < depth; i++)
|
||||
{
|
||||
std::stringstream stack_line;
|
||||
BOOL ret;
|
||||
|
||||
DWORD64 addr = (DWORD64)frames[i];
|
||||
ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
|
||||
if(ret)
|
||||
{
|
||||
stack_line << pSym->Name << " ";
|
||||
}
|
||||
|
||||
DWORD dummy;
|
||||
ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
|
||||
if(ret)
|
||||
{
|
||||
std::string file_name = line.FileName;
|
||||
std::string::size_type index = file_name.rfind("\\");
|
||||
stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber;
|
||||
}
|
||||
|
||||
lines.push_back(stack_line.str());
|
||||
}
|
||||
|
||||
free(pSym);
|
||||
|
||||
// TODO: figure out a way to cleanup symbol loading
|
||||
// Not hugely necessary, however.
|
||||
//SymCleanup(hProc);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
lines.push_back("Stack Trace Failed. PDB symbol info not loaded");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
bool ll_get_stack_trace(std::vector<std::string>& lines)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* @file llstacktrace.h
|
||||
* @brief stack trace functions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2001-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LL_LLSTACKTRACE_H
|
||||
#define LL_LLSTACKTRACE_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
bool ll_get_stack_trace(std::vector<std::string>& lines);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ public:
|
|||
static std::string filename();
|
||||
|
||||
protected:
|
||||
/* virtual */ void loadFile();
|
||||
/* virtual */ bool loadFile();
|
||||
|
||||
public:
|
||||
void init(LLPerfStats* statsp);
|
||||
|
|
@ -95,12 +95,12 @@ LLStatsConfigFile& LLStatsConfigFile::instance()
|
|||
|
||||
/* virtual */
|
||||
// Load and parse the stats configuration file
|
||||
void LLStatsConfigFile::loadFile()
|
||||
bool LLStatsConfigFile::loadFile()
|
||||
{
|
||||
if (!mStatsp)
|
||||
{
|
||||
llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
mChanged = true;
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ void LLStatsConfigFile::loadFile()
|
|||
{
|
||||
llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl;
|
||||
mStatsp->setReportPerformanceDuration( 0.f );
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -124,7 +124,7 @@ void LLStatsConfigFile::loadFile()
|
|||
llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl;
|
||||
mStatsp->setReportPerformanceDuration( 0.f );
|
||||
}
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,6 +160,7 @@ void LLStatsConfigFile::loadFile()
|
|||
{
|
||||
llinfos << "Performance stats recording turned off" << llendl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ struct char_traits<U16>
|
|||
};
|
||||
#endif
|
||||
|
||||
class LL_COMMON_API LLStringOps
|
||||
class LLStringOps
|
||||
{
|
||||
private:
|
||||
static long sltOffset;
|
||||
|
|
@ -194,13 +194,13 @@ public:
|
|||
* @brief Return a string constructed from in without crashing if the
|
||||
* pointer is NULL.
|
||||
*/
|
||||
LL_COMMON_API std::string ll_safe_string(const char* in);
|
||||
LL_COMMON_API std::string ll_safe_string(const char* in, S32 maxlen);
|
||||
std::string ll_safe_string(const char* in);
|
||||
std::string ll_safe_string(const char* in, S32 maxlen);
|
||||
|
||||
|
||||
// Allowing assignments from non-strings into format_map_t is apparently
|
||||
// *really* error-prone, so subclass std::string with just basic c'tors.
|
||||
class LL_COMMON_API LLFormatMapString
|
||||
class LLFormatMapString
|
||||
{
|
||||
public:
|
||||
LLFormatMapString() {};
|
||||
|
|
@ -254,7 +254,25 @@ public:
|
|||
|
||||
// True if this is the head of s.
|
||||
static BOOL isHead( const std::basic_string<T>& string, const T* s );
|
||||
|
||||
|
||||
/**
|
||||
* @brief Returns true if string starts with substr
|
||||
*
|
||||
* If etither string or substr are empty, this method returns false.
|
||||
*/
|
||||
static bool startsWith(
|
||||
const std::basic_string<T>& string,
|
||||
const std::basic_string<T>& substr);
|
||||
|
||||
/**
|
||||
* @brief Returns true if string ends in substr
|
||||
*
|
||||
* If etither string or substr are empty, this method returns false.
|
||||
*/
|
||||
static bool endsWith(
|
||||
const std::basic_string<T>& string,
|
||||
const std::basic_string<T>& substr);
|
||||
|
||||
static void addCRLF(std::basic_string<T>& string);
|
||||
static void removeCRLF(std::basic_string<T>& string);
|
||||
|
||||
|
|
@ -362,7 +380,7 @@ public:
|
|||
* This function works on bytes rather than glyphs, so this will
|
||||
* incorrectly truncate non-single byte strings.
|
||||
* Use utf8str_truncate() for utf8 strings
|
||||
* @return a copy of in string minus the trailing count characters.
|
||||
* @return a copy of in string minus the trailing count bytes.
|
||||
*/
|
||||
inline std::string chop_tail_copy(
|
||||
const std::string& in,
|
||||
|
|
@ -375,7 +393,7 @@ inline std::string chop_tail_copy(
|
|||
* @brief This translates a nybble stored as a hex value from 0-f back
|
||||
* to a nybble in the low order bits of the return byte.
|
||||
*/
|
||||
LL_COMMON_API U8 hex_as_nybble(char hex);
|
||||
U8 hex_as_nybble(char hex);
|
||||
|
||||
/**
|
||||
* @brief read the contents of a file into a string.
|
||||
|
|
@ -386,8 +404,8 @@ LL_COMMON_API U8 hex_as_nybble(char hex);
|
|||
* @param filename The full name of the file to read.
|
||||
* @return Returns true on success. If false, str is unmodified.
|
||||
*/
|
||||
LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename);
|
||||
LL_COMMON_API bool iswindividual(llwchar elem);
|
||||
bool _read_file_into_string(std::string& str, const std::string& filename);
|
||||
bool iswindividual(llwchar elem);
|
||||
|
||||
/**
|
||||
* Unicode support
|
||||
|
|
@ -396,52 +414,52 @@ LL_COMMON_API bool iswindividual(llwchar elem);
|
|||
// Make the incoming string a utf8 string. Replaces any unknown glyph
|
||||
// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest
|
||||
// of the data may not be recovered.
|
||||
LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw);
|
||||
std::string rawstr_to_utf8(const std::string& raw);
|
||||
|
||||
//
|
||||
// We should never use UTF16 except when communicating with Win32!
|
||||
//
|
||||
typedef std::basic_string<U16> llutf16string;
|
||||
|
||||
LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
|
||||
LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str);
|
||||
LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
|
||||
LLWString utf16str_to_wstring(const llutf16string &utf16str);
|
||||
|
||||
LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
|
||||
LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str);
|
||||
llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
|
||||
llutf16string wstring_to_utf16str(const LLWString &utf32str);
|
||||
|
||||
LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
|
||||
LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str );
|
||||
llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
|
||||
llutf16string utf8str_to_utf16str ( const std::string& utf8str );
|
||||
|
||||
LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
|
||||
LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str);
|
||||
LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
|
||||
LLWString utf8str_to_wstring(const std::string &utf8str);
|
||||
// Same function, better name. JC
|
||||
inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
|
||||
|
||||
//
|
||||
LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
|
||||
S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
|
||||
|
||||
LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
|
||||
LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str);
|
||||
std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
|
||||
std::string wstring_to_utf8str(const LLWString &utf32str);
|
||||
|
||||
LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
|
||||
LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str);
|
||||
std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
|
||||
std::string utf16str_to_utf8str(const llutf16string &utf16str);
|
||||
|
||||
// Length of this UTF32 string in bytes when transformed to UTF8
|
||||
LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr);
|
||||
S32 wstring_utf8_length(const LLWString& wstr);
|
||||
|
||||
// Length in bytes of this wide char in a UTF8 string
|
||||
LL_COMMON_API S32 wchar_utf8_length(const llwchar wc);
|
||||
S32 wchar_utf8_length(const llwchar wc);
|
||||
|
||||
LL_COMMON_API std::string utf8str_tolower(const std::string& utf8str);
|
||||
std::string utf8str_tolower(const std::string& utf8str);
|
||||
|
||||
// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
|
||||
LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
|
||||
S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
|
||||
|
||||
// Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
|
||||
LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
|
||||
S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
|
||||
|
||||
// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.)
|
||||
LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
|
||||
S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
|
||||
|
||||
/**
|
||||
* @brief Properly truncate a utf8 string to a maximum byte count.
|
||||
|
|
@ -453,11 +471,11 @@ LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wst
|
|||
* @param max_len The maximum number of bytes in the return value.
|
||||
* @return Returns a valid utf8 string with byte count <= max_len.
|
||||
*/
|
||||
LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
|
||||
std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
|
||||
|
||||
LL_COMMON_API std::string utf8str_trim(const std::string& utf8str);
|
||||
std::string utf8str_trim(const std::string& utf8str);
|
||||
|
||||
LL_COMMON_API S32 utf8str_compare_insensitive(
|
||||
S32 utf8str_compare_insensitive(
|
||||
const std::string& lhs,
|
||||
const std::string& rhs);
|
||||
|
||||
|
|
@ -468,17 +486,17 @@ LL_COMMON_API S32 utf8str_compare_insensitive(
|
|||
* @param target_char The wchar to be replaced
|
||||
* @param replace_char The wchar which is written on replace
|
||||
*/
|
||||
LL_COMMON_API std::string utf8str_substChar(
|
||||
std::string utf8str_substChar(
|
||||
const std::string& utf8str,
|
||||
const llwchar target_char,
|
||||
const llwchar replace_char);
|
||||
|
||||
LL_COMMON_API std::string utf8str_makeASCII(const std::string& utf8str);
|
||||
std::string utf8str_makeASCII(const std::string& utf8str);
|
||||
|
||||
// Hack - used for evil notecards.
|
||||
LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str);
|
||||
std::string mbcsstring_makeASCII(const std::string& str);
|
||||
|
||||
LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
|
||||
std::string utf8str_removeCRLF(const std::string& utf8str);
|
||||
|
||||
|
||||
#if LL_WINDOWS
|
||||
|
|
@ -503,21 +521,14 @@ LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
|
|||
* formatted string.
|
||||
*
|
||||
*/
|
||||
|
||||
// Deal with the differeneces on Windows
|
||||
namespace snprintf_hack
|
||||
{
|
||||
LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...);
|
||||
}
|
||||
|
||||
using snprintf_hack::snprintf;
|
||||
int safe_snprintf(char* str, size_t size, const char* format, ...);
|
||||
|
||||
/**
|
||||
* @brief Convert a wide string to std::string
|
||||
*
|
||||
* This replaces the unsafe W2A macro from ATL.
|
||||
*/
|
||||
LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in);
|
||||
std::string ll_convert_wide_to_string(const wchar_t* in);
|
||||
|
||||
//@}
|
||||
#endif // LL_WINDOWS
|
||||
|
|
@ -540,7 +551,7 @@ namespace LLStringFn
|
|||
* with zero non-printable characters.
|
||||
* @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
|
||||
*/
|
||||
LL_COMMON_API void replace_nonprintable_in_ascii(
|
||||
void replace_nonprintable_in_ascii(
|
||||
std::basic_string<char>& string,
|
||||
char replacement);
|
||||
|
||||
|
|
@ -554,7 +565,7 @@ namespace LLStringFn
|
|||
* with zero non-printable characters and zero pipe characters.
|
||||
* @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
|
||||
*/
|
||||
LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
|
||||
void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
|
||||
char replacement);
|
||||
|
||||
|
||||
|
|
@ -563,7 +574,7 @@ namespace LLStringFn
|
|||
* Returns a copy of the string with those characters removed.
|
||||
* Works with US ASCII and UTF-8 encoded strings. JC
|
||||
*/
|
||||
LL_COMMON_API std::string strip_invalid_xml(const std::string& input);
|
||||
std::string strip_invalid_xml(const std::string& input);
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -574,7 +585,7 @@ namespace LLStringFn
|
|||
* with zero non-printable characters.
|
||||
* @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
|
||||
*/
|
||||
LL_COMMON_API void replace_ascii_controlchars(
|
||||
void replace_ascii_controlchars(
|
||||
std::basic_string<char>& string,
|
||||
char replacement);
|
||||
}
|
||||
|
|
@ -757,15 +768,16 @@ bool LLStringUtilBase<T>::formatDatetime(std::basic_string<T>& replacement, std:
|
|||
{
|
||||
S32 secFromEpoch = (long) substitutions["datetime"].asInteger();
|
||||
|
||||
if (param == "local")
|
||||
if (param == "local") // local
|
||||
{
|
||||
secFromEpoch -= LLStringOps::getLocalTimeOffset();
|
||||
}
|
||||
else if (param != "utc")
|
||||
else if (param != "utc") // slt
|
||||
{
|
||||
secFromEpoch -= LLStringOps::getSltOffset();
|
||||
}
|
||||
|
||||
|
||||
// if never fell into those two ifs above, param must be utc
|
||||
if (secFromEpoch < 0) secFromEpoch = 0;
|
||||
|
||||
LLDate * datetime = new LLDate((F64)secFromEpoch);
|
||||
|
|
@ -1251,6 +1263,30 @@ BOOL LLStringUtilBase<T>::isHead( const std::basic_string<T>& string, const T* s
|
|||
}
|
||||
}
|
||||
|
||||
// static
|
||||
template<class T>
|
||||
bool LLStringUtilBase<T>::startsWith(
|
||||
const std::basic_string<T>& string,
|
||||
const std::basic_string<T>& substr)
|
||||
{
|
||||
if(string.empty() || (substr.empty())) return false;
|
||||
if(0 == string.find(substr)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
template<class T>
|
||||
bool LLStringUtilBase<T>::endsWith(
|
||||
const std::basic_string<T>& string,
|
||||
const std::basic_string<T>& substr)
|
||||
{
|
||||
if(string.empty() || (substr.empty())) return false;
|
||||
std::string::size_type idx = string.rfind(substr);
|
||||
if(std::string::npos == idx) return false;
|
||||
return (idx == (string.size() - substr.size()));
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
BOOL LLStringUtilBase<T>::convertToBOOL(const std::basic_string<T>& string, BOOL& value)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -581,7 +581,7 @@ LLEventTimer::~LLEventTimer()
|
|||
void LLEventTimer::updateClass()
|
||||
{
|
||||
std::list<LLEventTimer*> completed_timers;
|
||||
for (instance_iter iter = instancesBegin(); iter != instancesEnd(); )
|
||||
for (instance_iter iter = beginInstances(); iter != endInstances(); )
|
||||
{
|
||||
LLEventTimer* timer = *iter++;
|
||||
F32 et = timer->mEventTimer.getElapsedTimeF32();
|
||||
|
|
|
|||
|
|
@ -356,7 +356,7 @@ public:
|
|||
LLTreeDFSIter() {}
|
||||
|
||||
/// flags iterator logic to skip traversing children of current node on next increment
|
||||
void skipChildren(bool skip = true) { mSkipChildren = skip; }
|
||||
void skipDescendants(bool skip = true) { mSkipChildren = skip; }
|
||||
|
||||
private:
|
||||
/// leverage boost::iterator_facade
|
||||
|
|
@ -453,7 +453,8 @@ public:
|
|||
/// each node.
|
||||
LLTreeDFSPostIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc):
|
||||
mBeginFunc(beginfunc),
|
||||
mEndFunc(endfunc)
|
||||
mEndFunc(endfunc),
|
||||
mSkipAncestors(false)
|
||||
{
|
||||
if (! node)
|
||||
return;
|
||||
|
|
@ -463,6 +464,9 @@ public:
|
|||
/// Instantiate an LLTreeDFSPostIter to mark the end of the walk
|
||||
LLTreeDFSPostIter() {}
|
||||
|
||||
/// flags iterator logic to skip traversing ancestors of current node on next increment
|
||||
void skipAncestors(bool skip = true) { mSkipAncestors = skip; }
|
||||
|
||||
private:
|
||||
/// leverage boost::iterator_facade
|
||||
friend class boost::iterator_core_access;
|
||||
|
|
@ -480,11 +484,25 @@ private:
|
|||
/// implement dereference/indirection operators
|
||||
ptr_type& dereference() const { return const_cast<ptr_type&>(mPending.back().first); }
|
||||
|
||||
struct isOpen
|
||||
{
|
||||
bool operator()(const typename list_type::value_type& item)
|
||||
{
|
||||
return item.second;
|
||||
}
|
||||
};
|
||||
|
||||
/// Call this each time we change mPending.back() -- that is, every time
|
||||
/// we're about to change the value returned by dereference(). If we
|
||||
/// haven't yet pushed the new node's children, do so now.
|
||||
void makeCurrent()
|
||||
{
|
||||
if (mSkipAncestors)
|
||||
{
|
||||
mPending.erase(std::remove_if(mPending.begin(), mPending.end(), isOpen()), mPending.end());
|
||||
mSkipAncestors = false;
|
||||
}
|
||||
|
||||
// Once we've popped the last node, this becomes a no-op.
|
||||
if (mPending.empty())
|
||||
return;
|
||||
|
|
@ -524,11 +542,13 @@ private:
|
|||
}
|
||||
|
||||
/// list of the nodes yet to be processed
|
||||
list_type mPending;
|
||||
list_type mPending;
|
||||
/// functor to extract begin() child iterator
|
||||
func_type mBeginFunc;
|
||||
func_type mBeginFunc;
|
||||
/// functor to extract end() child iterator
|
||||
func_type mEndFunc;
|
||||
func_type mEndFunc;
|
||||
/// flags logic to skip traversal of ancestors of current node
|
||||
bool mSkipAncestors;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -162,11 +162,10 @@ namespace
|
|||
{ return LLURI::escape(s, unreserved() + ":@!$'()*+,="); } // sub_delims - "&;" + ":@"
|
||||
}
|
||||
|
||||
// *TODO: Consider using curl. After http textures gets merged everywhere.
|
||||
// static
|
||||
//static
|
||||
std::string LLURI::escape(const std::string& str)
|
||||
{
|
||||
static std::string default_allowed(unreserved() + ":@!$'()*+,=/?&#;");
|
||||
static std::string default_allowed = unreserved();
|
||||
static bool initialized = false;
|
||||
if(!initialized)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -127,27 +127,16 @@ public:
|
|||
/** @name Escaping Utilities */
|
||||
//@{
|
||||
/**
|
||||
* @brief Escape a raw url with a reasonable set of allowed characters.
|
||||
*
|
||||
* The default set was chosen to match HTTP urls and general
|
||||
* guidelines for naming resources. Passing in a raw url does not
|
||||
* produce well defined results because you really need to know
|
||||
* which segments are path parts because path parts are supposed
|
||||
* to be escaped individually. The default set chosen is:
|
||||
* @brief Escape the string passed except for unreserved
|
||||
*
|
||||
* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
|
||||
* 0123456789
|
||||
* -._~
|
||||
* :@!$'()*+,=/?&#;
|
||||
*
|
||||
* *NOTE: This API is basically broken because it does not
|
||||
* allow you to specify significant path characters. For example,
|
||||
* if the filename actually contained a /, then you cannot use
|
||||
* this function to generate the serialized url for that
|
||||
* resource.
|
||||
* @see http://www.ietf.org/rfc/rfc1738.txt
|
||||
*
|
||||
* @param str The raw URI to escape.
|
||||
* @return Returns the escaped uri or an empty string.
|
||||
* @return Returns the rfc 1738 escaped uri or an empty string.
|
||||
*/
|
||||
static std::string escape(const std::string& str);
|
||||
|
||||
|
|
|
|||
|
|
@ -34,9 +34,9 @@
|
|||
#define LL_LLVERSIONSERVER_H
|
||||
|
||||
const S32 LL_VERSION_MAJOR = 1;
|
||||
const S32 LL_VERSION_MINOR = 27;
|
||||
const S32 LL_VERSION_MINOR = 29;
|
||||
const S32 LL_VERSION_PATCH = 0;
|
||||
const S32 LL_VERSION_BUILD = 118914;
|
||||
const S32 LL_VERSION_BUILD = 120909;
|
||||
|
||||
const char * const LL_CHANNEL = "Second Life Server";
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,6 @@ const S32 LL_VERSION_MINOR = 0;
|
|||
const S32 LL_VERSION_PATCH = 0;
|
||||
const S32 LL_VERSION_BUILD = 0;
|
||||
|
||||
const char * const LL_CHANNEL = "Second Life Release";
|
||||
const char * const LL_CHANNEL = "Second Life 2009";
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,150 @@
|
|||
/**
|
||||
* @file llallocator_heap_profile_test.cpp
|
||||
* @author Brad Kittenbrink
|
||||
* @date 2008-02-
|
||||
* @brief Test for llallocator_heap_profile.cpp.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "../llallocator_heap_profile.h"
|
||||
#include "../test/lltut.h"
|
||||
|
||||
namespace tut
|
||||
{
|
||||
struct llallocator_heap_profile_data
|
||||
{
|
||||
LLAllocatorHeapProfile prof;
|
||||
|
||||
static char const * const sample_win_profile;
|
||||
// *TODO - get test output from mac/linux tcmalloc
|
||||
static char const * const sample_mac_profile;
|
||||
static char const * const sample_lin_profile;
|
||||
|
||||
static char const * const crash_testcase;
|
||||
};
|
||||
typedef test_group<llallocator_heap_profile_data> factory;
|
||||
typedef factory::object object;
|
||||
}
|
||||
namespace
|
||||
{
|
||||
tut::factory llallocator_heap_profile_test_factory("LLAllocatorHeapProfile");
|
||||
}
|
||||
|
||||
namespace tut
|
||||
{
|
||||
template<> template<>
|
||||
void object::test<1>()
|
||||
{
|
||||
prof.parse(sample_win_profile);
|
||||
|
||||
ensure_equals("count lines", prof.mLines.size() , 5);
|
||||
ensure_equals("alloc counts", prof.mLines[0].mLiveCount, 2131854U);
|
||||
ensure_equals("alloc counts", prof.mLines[0].mLiveSize, 2245710106ULL);
|
||||
ensure_equals("alloc counts", prof.mLines[0].mTotalCount, 14069198U);
|
||||
ensure_equals("alloc counts", prof.mLines[0].mTotalSize, 4295177308ULL);
|
||||
ensure_equals("count markers", prof.mLines[0].mTrace.size(), 0);
|
||||
ensure_equals("count markers", prof.mLines[1].mTrace.size(), 0);
|
||||
ensure_equals("count markers", prof.mLines[2].mTrace.size(), 4);
|
||||
ensure_equals("count markers", prof.mLines[3].mTrace.size(), 6);
|
||||
ensure_equals("count markers", prof.mLines[4].mTrace.size(), 7);
|
||||
|
||||
//prof.dump(std::cout);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<2>()
|
||||
{
|
||||
prof.parse(crash_testcase);
|
||||
|
||||
ensure_equals("count lines", prof.mLines.size(), 2);
|
||||
ensure_equals("alloc counts", prof.mLines[0].mLiveCount, 3U);
|
||||
ensure_equals("alloc counts", prof.mLines[0].mLiveSize, 1049652ULL);
|
||||
ensure_equals("alloc counts", prof.mLines[0].mTotalCount, 8U);
|
||||
ensure_equals("alloc counts", prof.mLines[0].mTotalSize, 1049748ULL);
|
||||
ensure_equals("count markers", prof.mLines[0].mTrace.size(), 0);
|
||||
ensure_equals("count markers", prof.mLines[1].mTrace.size(), 0);
|
||||
|
||||
//prof.dump(std::cout);
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
void object::test<3>()
|
||||
{
|
||||
// test that we don't crash on edge case data
|
||||
prof.parse("");
|
||||
ensure("emtpy on error", prof.mLines.empty());
|
||||
|
||||
prof.parse("heap profile:");
|
||||
ensure("emtpy on error", prof.mLines.empty());
|
||||
}
|
||||
|
||||
char const * const llallocator_heap_profile_data::sample_win_profile =
|
||||
"heap profile: 2131854: 2245710106 [14069198: 4295177308] @\n"
|
||||
"308592: 1073398388 [966564: 1280998739] @\n"
|
||||
"462651: 375969538 [1177377: 753561247] @ 2 3 6 1\n"
|
||||
"314744: 206611283 [2008722: 570934755] @ 2 3 3 7 21 32\n"
|
||||
"277152: 82862770 [621961: 168503640] @ 2 3 3 7 21 32 87\n"
|
||||
"\n"
|
||||
"MAPPED_LIBRARIES:\n"
|
||||
"00400000-02681000 r-xp 00000000 00:00 0 c:\\proj\\tcmalloc-eval-9\\indra\\build-vc80\\newview\\RelWithDebInfo\\secondlife-bin.exe\n"
|
||||
"77280000-773a7000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\ntdll.dll\n"
|
||||
"76df0000-76ecb000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\kernel32.dll\n"
|
||||
"76000000-76073000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\comdlg32.dll\n"
|
||||
"75ee0000-75f8a000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\msvcrt.dll\n"
|
||||
"76c30000-76c88000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\SHLWAPI.dll\n"
|
||||
"75f90000-75fdb000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\GDI32.dll\n"
|
||||
"77420000-774bd000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\USER32.dll\n"
|
||||
"75e10000-75ed6000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\ADVAPI32.dll\n"
|
||||
"75b00000-75bc2000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\RPCRT4.dll\n"
|
||||
"72ca0000-72d25000 r-xp 00000000 00:00 0 C:\\Windows\\WinSxS\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.6001.18000_none_886786f450a74a05\\COMCTL32.dll\n"
|
||||
"76120000-76c30000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\SHELL32.dll\n"
|
||||
"71ce0000-71d13000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\DINPUT8.dll\n";
|
||||
|
||||
|
||||
char const * const llallocator_heap_profile_data::crash_testcase =
|
||||
"heap profile: 3: 1049652 [ 8: 1049748] @\n"
|
||||
" 3: 1049652 [ 8: 1049748] @\n"
|
||||
"\n"
|
||||
"MAPPED_LIBRARIES:\n"
|
||||
"00400000-004d5000 r-xp 00000000 00:00 0 c:\\code\\linden\\tcmalloc\\indra\\build-vc80\\llcommon\\RelWithDebInfo\\llallocator_test.exe\n"
|
||||
"7c900000-7c9af000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\ntdll.dll\n"
|
||||
"7c800000-7c8f6000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\kernel32.dll\n"
|
||||
"77dd0000-77e6b000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\ADVAPI32.dll\n"
|
||||
"77e70000-77f02000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\RPCRT4.dll\n"
|
||||
"77fe0000-77ff1000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\Secur32.dll\n"
|
||||
"71ab0000-71ac7000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\WS2_32.dll\n"
|
||||
"77c10000-77c68000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\msvcrt.dll\n"
|
||||
"71aa0000-71aa8000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\WS2HELP.dll\n"
|
||||
"76bf0000-76bfb000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\PSAPI.DLL\n"
|
||||
"5b860000-5b8b5000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\NETAPI32.dll\n"
|
||||
"10000000-10041000 r-xp 00000000 00:00 0 c:\\code\\linden\\tcmalloc\\indra\\build-vc80\\llcommon\\RelWithDebInfo\\libtcmalloc_minimal.dll\n"
|
||||
"7c420000-7c4a7000 r-xp 00000000 00:00 0 C:\\WINDOWS\\WinSxS\\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.1433_x-ww_5cf844d2\\MSVCP80.dll\n"
|
||||
"78130000-781cb000 r-xp 00000000 00:00 0 C:\\WINDOWS\\WinSxS\\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.1433_x-ww_5cf844d2\\MSVCR80.dll\n";
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* @file llallocator_test.cpp
|
||||
* @author Brad Kittenbrink
|
||||
* @date 2008-02-
|
||||
* @brief Test for llallocator.cpp.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "../llallocator.h"
|
||||
#include "../test/lltut.h"
|
||||
|
||||
namespace tut
|
||||
{
|
||||
struct llallocator_data
|
||||
{
|
||||
LLAllocator llallocator;
|
||||
};
|
||||
typedef test_group<llallocator_data> factory;
|
||||
typedef factory::object object;
|
||||
}
|
||||
namespace
|
||||
{
|
||||
tut::factory llallocator_test_factory("LLAllocator");
|
||||
}
|
||||
|
||||
namespace tut
|
||||
{
|
||||
template<> template<>
|
||||
void object::test<1>()
|
||||
{
|
||||
llallocator.setProfilingEnabled(false);
|
||||
ensure("Profiler disable", !llallocator.isProfiling());
|
||||
}
|
||||
|
||||
#if LL_USE_TCMALLOC
|
||||
template<> template<>
|
||||
void object::test<2>()
|
||||
{
|
||||
llallocator.setProfilingEnabled(true);
|
||||
ensure("Profiler enable", llallocator.isProfiling());
|
||||
}
|
||||
|
||||
template <> template <>
|
||||
void object::test<3>()
|
||||
{
|
||||
llallocator.setProfilingEnabled(true);
|
||||
|
||||
char * test_alloc = new char[1024];
|
||||
|
||||
llallocator.getProfile();
|
||||
|
||||
delete [] test_alloc;
|
||||
|
||||
llallocator.getProfile();
|
||||
|
||||
// *NOTE - this test isn't ensuring anything right now other than no
|
||||
// exceptions are thrown.
|
||||
}
|
||||
#endif // LL_USE_TCMALLOC
|
||||
};
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* @file llmemtype_test.cpp
|
||||
* @author Palmer Truelson
|
||||
* @date 2008-03-
|
||||
* @brief Test for llmemtype.cpp.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2009&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2009-2009, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#include "../llmemtype.h"
|
||||
#include "../test/lltut.h"
|
||||
#include "../llallocator.h"
|
||||
|
||||
|
||||
#include <stack>
|
||||
|
||||
std::stack<S32> memTypeStack;
|
||||
|
||||
void LLAllocator::pushMemType(S32 i)
|
||||
{
|
||||
memTypeStack.push(i);
|
||||
}
|
||||
|
||||
S32 LLAllocator::popMemType(void)
|
||||
{
|
||||
S32 ret = memTypeStack.top();
|
||||
memTypeStack.pop();
|
||||
return ret;
|
||||
}
|
||||
|
||||
namespace tut
|
||||
{
|
||||
struct llmemtype_data
|
||||
{
|
||||
};
|
||||
|
||||
typedef test_group<llmemtype_data> factory;
|
||||
typedef factory::object object;
|
||||
}
|
||||
namespace
|
||||
{
|
||||
tut::factory llmemtype_test_factory("LLMemType");
|
||||
}
|
||||
|
||||
namespace tut
|
||||
{
|
||||
template<> template<>
|
||||
void object::test<1>()
|
||||
{
|
||||
ensure("Simplest test ever", true);
|
||||
}
|
||||
|
||||
// test with no scripts
|
||||
template<> template<>
|
||||
void object::test<2>()
|
||||
{
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_INIT);
|
||||
}
|
||||
ensure("Test that you can construct and destruct the mem type");
|
||||
}
|
||||
|
||||
// test creation and stack testing
|
||||
template<> template<>
|
||||
void object::test<3>()
|
||||
{
|
||||
{
|
||||
ensure("Test that creation and destruction properly inc/dec the stack");
|
||||
ensure_equals(memTypeStack.size(), 0);
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_INIT);
|
||||
ensure_equals(memTypeStack.size(), 1);
|
||||
LLMemType m2(LLMemType::MTYPE_STARTUP);
|
||||
ensure_equals(memTypeStack.size(), 2);
|
||||
}
|
||||
ensure_equals(memTypeStack.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
// test with no scripts
|
||||
template<> template<>
|
||||
void object::test<4>()
|
||||
{
|
||||
// catch the begining and end
|
||||
std::string test_name = LLMemType::getNameFromID(LLMemType::MTYPE_INIT.mID);
|
||||
ensure_equals("Init name", test_name, "Init");
|
||||
|
||||
std::string test_name2 = LLMemType::getNameFromID(LLMemType::MTYPE_VOLUME.mID);
|
||||
ensure_equals("Volume name", test_name2, "Volume");
|
||||
|
||||
std::string test_name3 = LLMemType::getNameFromID(LLMemType::MTYPE_OTHER.mID);
|
||||
ensure_equals("Other name", test_name3, "Other");
|
||||
|
||||
std::string test_name4 = LLMemType::getNameFromID(-1);
|
||||
ensure_equals("Invalid name", test_name4, "INVALID");
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -90,7 +90,8 @@ LLCrashLogger::LLCrashLogger() :
|
|||
mSentCrashLogs(false),
|
||||
mCrashHost("")
|
||||
{
|
||||
|
||||
// Set up generic error handling
|
||||
setupErrorHandling();
|
||||
}
|
||||
|
||||
LLCrashLogger::~LLCrashLogger()
|
||||
|
|
@ -208,7 +209,10 @@ void LLCrashLogger::gatherFiles()
|
|||
mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml");
|
||||
}
|
||||
|
||||
#if !LL_DARWIN
|
||||
if(mCrashInPreviousExec)
|
||||
#else
|
||||
#endif
|
||||
{
|
||||
// Replace the log file ext with .old, since the
|
||||
// instance that launched this process has overwritten
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ void LLImageBase::deleteData()
|
|||
// virtual
|
||||
U8* LLImageBase::allocateData(S32 size)
|
||||
{
|
||||
LLMemType mt1((LLMemType::EMemType)mMemType);
|
||||
LLMemType mt1(mMemType);
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
|
|
@ -188,7 +188,7 @@ U8* LLImageBase::allocateData(S32 size)
|
|||
// virtual
|
||||
U8* LLImageBase::reallocateData(S32 size)
|
||||
{
|
||||
LLMemType mt1((LLMemType::EMemType)mMemType);
|
||||
LLMemType mt1(mMemType);
|
||||
U8 *new_datap = new U8[size];
|
||||
if (!new_datap)
|
||||
{
|
||||
|
|
@ -332,7 +332,7 @@ BOOL LLImageRaw::resize(U16 width, U16 height, S8 components)
|
|||
|
||||
U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const
|
||||
{
|
||||
LLMemType mt1((LLMemType::EMemType)mMemType);
|
||||
LLMemType mt1(mMemType);
|
||||
U8 *data = new U8[width*height*getComponents()];
|
||||
|
||||
// Should do some simple bounds checking
|
||||
|
|
@ -415,7 +415,7 @@ void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a)
|
|||
// Reverses the order of the rows in the image
|
||||
void LLImageRaw::verticalFlip()
|
||||
{
|
||||
LLMemType mt1((LLMemType::EMemType)mMemType);
|
||||
LLMemType mt1(mMemType);
|
||||
S32 row_bytes = getWidth() * getComponents();
|
||||
llassert(row_bytes > 0);
|
||||
std::vector<U8> line_buffer(row_bytes);
|
||||
|
|
@ -548,7 +548,7 @@ void LLImageRaw::composite( LLImageRaw* src )
|
|||
// Src and dst can be any size. Src has 4 components. Dst has 3 components.
|
||||
void LLImageRaw::compositeScaled4onto3(LLImageRaw* src)
|
||||
{
|
||||
LLMemType mt1((LLMemType::EMemType)mMemType);
|
||||
LLMemType mt1(mMemType);
|
||||
llinfos << "compositeScaled4onto3" << llendl;
|
||||
|
||||
LLImageRaw* dst = this; // Just for clarity.
|
||||
|
|
@ -787,7 +787,7 @@ void LLImageRaw::copyUnscaled3onto4( LLImageRaw* src )
|
|||
// Src and dst can be any size. Src and dst have same number of components.
|
||||
void LLImageRaw::copyScaled( LLImageRaw* src )
|
||||
{
|
||||
LLMemType mt1((LLMemType::EMemType)mMemType);
|
||||
LLMemType mt1(mMemType);
|
||||
LLImageRaw* dst = this; // Just for clarity.
|
||||
|
||||
llassert_always( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) );
|
||||
|
|
@ -819,7 +819,7 @@ void LLImageRaw::copyScaled( LLImageRaw* src )
|
|||
|
||||
BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data )
|
||||
{
|
||||
LLMemType mt1((LLMemType::EMemType)mMemType);
|
||||
LLMemType mt1(mMemType);
|
||||
llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) );
|
||||
|
||||
S32 old_width = getWidth();
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
#include "llstring.h"
|
||||
//#include "llmemory.h"
|
||||
#include "llthread.h"
|
||||
#include "llmemtype.h"
|
||||
|
||||
const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2
|
||||
const S32 MAX_IMAGE_MIP = 11; // 2048x2048
|
||||
|
|
@ -155,7 +156,7 @@ private:
|
|||
BOOL mBadBufferAllocation ;
|
||||
|
||||
public:
|
||||
S16 mMemType; // debug
|
||||
LLMemType::DeclareMemType& mMemType; // debug
|
||||
|
||||
static BOOL sSizeOverride;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time)
|
|||
|
||||
BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count )
|
||||
{
|
||||
LLMemType mt1((LLMemType::EMemType)mMemType);
|
||||
LLMemType mt1(mMemType);
|
||||
|
||||
BOOL res = TRUE;
|
||||
|
||||
|
|
@ -329,7 +329,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time)
|
|||
|
||||
BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time)
|
||||
{
|
||||
LLMemType mt1((LLMemType::EMemType)mMemType);
|
||||
LLMemType mt1(mMemType);
|
||||
resetLastError();
|
||||
BOOL res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible);
|
||||
if (!mLastError.empty())
|
||||
|
|
@ -462,7 +462,7 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename)
|
|||
|
||||
BOOL LLImageJ2C::validate(U8 *data, U32 file_size)
|
||||
{
|
||||
LLMemType mt1((LLMemType::EMemType)mMemType);
|
||||
LLMemType mt1(mMemType);
|
||||
|
||||
resetLastError();
|
||||
|
||||
|
|
|
|||
|
|
@ -705,8 +705,8 @@ BOOL LLInventoryItem::exportFile(LLFILE* fp, BOOL include_asset_key) const
|
|||
fprintf(fp, "\t\tasset_id\t%s\n", uuid_str.c_str());
|
||||
}
|
||||
fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
|
||||
const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
|
||||
if(inv_type_str) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str);
|
||||
const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
|
||||
if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str());
|
||||
fprintf(fp, "\t\tflags\t%08x\n", mFlags);
|
||||
mSaleInfo.exportFile(fp);
|
||||
fprintf(fp, "\t\tname\t%s|\n", mName.c_str());
|
||||
|
|
@ -908,8 +908,8 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu
|
|||
output_stream << "\t\tasset_id\t" << uuid_str << "\n";
|
||||
}
|
||||
output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n";
|
||||
const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
|
||||
if(inv_type_str)
|
||||
const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
|
||||
if(!inv_type_str.empty())
|
||||
output_stream << "\t\tinv_type\t" << inv_type_str << "\n";
|
||||
std::string buffer;
|
||||
buffer = llformat( "\t\tflags\t%08x\n", mFlags);
|
||||
|
|
@ -951,8 +951,8 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
|
|||
}
|
||||
sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
|
||||
sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType;
|
||||
const char* inv_type_str = LLInventoryType::lookup(mInventoryType);
|
||||
if(inv_type_str)
|
||||
const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
|
||||
if(!inv_type_str.empty())
|
||||
{
|
||||
sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,9 +92,9 @@ public:
|
|||
// accessors
|
||||
virtual const LLUUID& getUUID() const;
|
||||
const LLUUID& getParentUUID() const;
|
||||
const std::string& getName() const;
|
||||
LLAssetType::EType getType() const;
|
||||
|
||||
virtual const std::string& getName() const;
|
||||
virtual LLAssetType::EType getType() const;
|
||||
LLAssetType::EType getActualType() const { return mType; }
|
||||
// mutators - will not call updateServer();
|
||||
void setUUID(const LLUUID& new_uuid);
|
||||
void rename(const std::string& new_name);
|
||||
|
|
@ -217,6 +217,7 @@ protected:
|
|||
~LLInventoryItem(); // ref counted
|
||||
|
||||
public:
|
||||
|
||||
MEM_TYPE_NEW(LLMemType::MTYPE_INVENTORY);
|
||||
LLInventoryItem(const LLUUID& uuid,
|
||||
const LLUUID& parent_uuid,
|
||||
|
|
@ -241,7 +242,7 @@ public:
|
|||
// accessors
|
||||
const LLPermissions& getPermissions() const;
|
||||
const LLUUID& getCreatorUUID() const;
|
||||
const LLUUID& getAssetUUID() const;
|
||||
virtual const LLUUID& getAssetUUID() const;
|
||||
const std::string& getDescription() const;
|
||||
const LLSaleInfo& getSaleInfo() const;
|
||||
LLInventoryType::EType getInventoryType() const;
|
||||
|
|
|
|||
|
|
@ -33,68 +33,59 @@
|
|||
#include "linden_common.h"
|
||||
|
||||
#include "llinventorytype.h"
|
||||
#include "lldictionary.h"
|
||||
#include "llmemory.h"
|
||||
#include "llsingleton.h"
|
||||
|
||||
static const std::string empty_string;
|
||||
|
||||
///----------------------------------------------------------------------------
|
||||
/// Class LLInventoryType
|
||||
///----------------------------------------------------------------------------
|
||||
|
||||
// Unlike asset type names, not limited to 8 characters.
|
||||
// Need not match asset type names.
|
||||
static const char* INVENTORY_TYPE_NAMES[LLInventoryType::IT_COUNT] =
|
||||
{
|
||||
"texture", // 0
|
||||
"sound",
|
||||
"callcard",
|
||||
"landmark",
|
||||
NULL,
|
||||
NULL, // 5
|
||||
"object",
|
||||
"notecard",
|
||||
"category",
|
||||
"root",
|
||||
"script", // 10
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
"snapshot", // 15
|
||||
NULL,
|
||||
"attach",
|
||||
"wearable",
|
||||
"animation",
|
||||
"gesture", // 20
|
||||
"favorite" //21
|
||||
struct InventoryEntry : public LLDictionaryEntry
|
||||
{
|
||||
InventoryEntry(const std::string &name,
|
||||
const std::string &human_name,
|
||||
int num_asset_types = 0, ...);
|
||||
const std::string mHumanName;
|
||||
typedef std::vector<LLAssetType::EType> asset_vec_t;
|
||||
asset_vec_t mAssetTypes;
|
||||
};
|
||||
|
||||
// This table is meant for decoding to human readable form. Put any
|
||||
// and as many printable characters you want in each one.
|
||||
// See also LLAssetType::mAssetTypeHumanNames
|
||||
static const char* INVENTORY_TYPE_HUMAN_NAMES[LLInventoryType::IT_COUNT] =
|
||||
{
|
||||
"texture", // 0
|
||||
"sound",
|
||||
"calling card",
|
||||
"landmark",
|
||||
NULL,
|
||||
NULL, // 5
|
||||
"object",
|
||||
"note card",
|
||||
"folder",
|
||||
"root",
|
||||
"script", // 10
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
"snapshot", // 15
|
||||
NULL,
|
||||
"attachment",
|
||||
"wearable",
|
||||
"animation",
|
||||
"gesture", // 20
|
||||
"favorite" // 21
|
||||
class LLInventoryDictionary : public LLSingleton<LLInventoryDictionary>,
|
||||
public LLDictionary<LLInventoryType::EType, InventoryEntry>
|
||||
{
|
||||
public:
|
||||
LLInventoryDictionary();
|
||||
};
|
||||
|
||||
LLInventoryDictionary::LLInventoryDictionary()
|
||||
{
|
||||
addEntry(LLInventoryType::IT_TEXTURE, new InventoryEntry("texture", "texture", 1, LLAssetType::AT_TEXTURE));
|
||||
addEntry(LLInventoryType::IT_SOUND, new InventoryEntry("sound", "sound", 1, LLAssetType::AT_SOUND));
|
||||
addEntry(LLInventoryType::IT_CALLINGCARD, new InventoryEntry("callcard", "calling card", 1, LLAssetType::AT_CALLINGCARD));
|
||||
addEntry(LLInventoryType::IT_LANDMARK, new InventoryEntry("landmark", "landmark", 1, LLAssetType::AT_LANDMARK));
|
||||
//addEntry(LLInventoryType::IT_SCRIPT, new InventoryEntry(NULL,NULL));
|
||||
//addEntry(LLInventoryType::IT_CLOTHING, new InventoryEntry(NULL,NULL));
|
||||
addEntry(LLInventoryType::IT_OBJECT, new InventoryEntry("object", "object", 1, LLAssetType::AT_OBJECT));
|
||||
addEntry(LLInventoryType::IT_NOTECARD, new InventoryEntry("notecard", "note card", 1, LLAssetType::AT_NOTECARD));
|
||||
addEntry(LLInventoryType::IT_CATEGORY, new InventoryEntry("category", "folder" ));
|
||||
addEntry(LLInventoryType::IT_ROOT_CATEGORY, new InventoryEntry("root", "root" ));
|
||||
addEntry(LLInventoryType::IT_LSL, new InventoryEntry("script", "script", 2, LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE));
|
||||
//addEntry(LLInventoryType::IT_LSL_BYTECODE, new InventoryEntry(NULL,NULL));
|
||||
//addEntry(LLInventoryType::IT_TEXTURE_TGA, new InventoryEntry(NULL,NULL));
|
||||
//addEntry(LLInventoryType::IT_BODYPART, new InventoryEntry(NULL,NULL));
|
||||
//addEntry(LLInventoryType::IT_TRASH, new InventoryEntry(NULL,NULL));
|
||||
addEntry(LLInventoryType::IT_SNAPSHOT, new InventoryEntry("snapshot", "snapshot", 1, LLAssetType::AT_TEXTURE));
|
||||
//addEntry(LLInventoryType::IT_LOST_AND_FOUND, new InventoryEntry(NULL,NULL, ));
|
||||
addEntry(LLInventoryType::IT_ATTACHMENT, new InventoryEntry("attach", "attachment", 1, LLAssetType::AT_OBJECT));
|
||||
addEntry(LLInventoryType::IT_WEARABLE, new InventoryEntry("wearable", "wearable", 2, LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART));
|
||||
addEntry(LLInventoryType::IT_ANIMATION, new InventoryEntry("animation", "animation", 1, LLAssetType::AT_ANIMATION));
|
||||
addEntry(LLInventoryType::IT_GESTURE, new InventoryEntry("gesture", "gesture", 1, LLAssetType::AT_GESTURE));
|
||||
addEntry(LLInventoryType::IT_FAVORITE, new InventoryEntry("favorite", "favorite", 1, LLAssetType::AT_FAVORITE));
|
||||
}
|
||||
|
||||
|
||||
// Maps asset types to the default inventory type for that kind of asset.
|
||||
// Thus, "Lost and Found" is a "Category"
|
||||
static const LLInventoryType::EType
|
||||
|
|
@ -122,78 +113,48 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
|
|||
LLInventoryType::IT_NONE, // AT_IMAGE_JPEG
|
||||
LLInventoryType::IT_ANIMATION, // AT_ANIMATION
|
||||
LLInventoryType::IT_GESTURE, // AT_GESTURE
|
||||
LLInventoryType::IT_NONE, // AT_LINK
|
||||
LLInventoryType::IT_FAVORITE, // AT_FAVORITE
|
||||
};
|
||||
|
||||
static const int MAX_POSSIBLE_ASSET_TYPES = 2;
|
||||
static const LLAssetType::EType
|
||||
INVENTORY_TO_ASSET_TYPE[LLInventoryType::IT_COUNT][MAX_POSSIBLE_ASSET_TYPES] =
|
||||
InventoryEntry::InventoryEntry(const std::string &name,
|
||||
const std::string &human_name,
|
||||
int num_asset_types, ...) :
|
||||
LLDictionaryEntry(name),
|
||||
mHumanName(human_name)
|
||||
{
|
||||
{ LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_TEXTURE
|
||||
{ LLAssetType::AT_SOUND, LLAssetType::AT_NONE }, // IT_SOUND
|
||||
{ LLAssetType::AT_CALLINGCARD, LLAssetType::AT_NONE }, // IT_CALLINGCARD
|
||||
{ LLAssetType::AT_LANDMARK, LLAssetType::AT_NONE }, // IT_LANDMARK
|
||||
{ LLAssetType::AT_NONE, LLAssetType::AT_NONE },
|
||||
{ LLAssetType::AT_NONE, LLAssetType::AT_NONE },
|
||||
{ LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_OBJECT
|
||||
{ LLAssetType::AT_NOTECARD, LLAssetType::AT_NONE }, // IT_NOTECARD
|
||||
{ LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_CATEGORY
|
||||
{ LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_ROOT_CATEGORY
|
||||
{ LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE }, // IT_LSL
|
||||
{ LLAssetType::AT_NONE, LLAssetType::AT_NONE },
|
||||
{ LLAssetType::AT_NONE, LLAssetType::AT_NONE },
|
||||
{ LLAssetType::AT_NONE, LLAssetType::AT_NONE },
|
||||
{ LLAssetType::AT_NONE, LLAssetType::AT_NONE },
|
||||
{ LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_SNAPSHOT
|
||||
{ LLAssetType::AT_NONE, LLAssetType::AT_NONE },
|
||||
{ LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_ATTACHMENT
|
||||
{ LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART }, // IT_WEARABLE
|
||||
{ LLAssetType::AT_ANIMATION, LLAssetType::AT_NONE }, // IT_ANIMATION
|
||||
{ LLAssetType::AT_GESTURE, LLAssetType::AT_NONE }, // IT_GESTURE
|
||||
{ LLAssetType::AT_FAVORITE, LLAssetType::AT_NONE }, // IT_FAVORITE
|
||||
};
|
||||
va_list argp;
|
||||
va_start(argp, num_asset_types);
|
||||
// Read in local textures
|
||||
for (U8 i=0; i < num_asset_types; i++)
|
||||
{
|
||||
LLAssetType::EType t = (LLAssetType::EType)va_arg(argp,int);
|
||||
mAssetTypes.push_back(t);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
const char* LLInventoryType::lookup(EType type)
|
||||
const std::string &LLInventoryType::lookup(EType type)
|
||||
{
|
||||
if((type >= 0) && (type < IT_COUNT))
|
||||
{
|
||||
return INVENTORY_TYPE_NAMES[S32(type)];
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(type);
|
||||
if (!entry) return empty_string;
|
||||
return entry->mName;
|
||||
}
|
||||
|
||||
// static
|
||||
LLInventoryType::EType LLInventoryType::lookup(const std::string& name)
|
||||
{
|
||||
for(S32 i = 0; i < IT_COUNT; ++i)
|
||||
{
|
||||
if((INVENTORY_TYPE_NAMES[i])
|
||||
&& (name == INVENTORY_TYPE_NAMES[i]))
|
||||
{
|
||||
// match
|
||||
return (EType)i;
|
||||
}
|
||||
}
|
||||
return IT_NONE;
|
||||
return LLInventoryDictionary::getInstance()->lookup(name);
|
||||
}
|
||||
|
||||
// XUI:translate
|
||||
// translation from a type to a human readable form.
|
||||
// static
|
||||
const char* LLInventoryType::lookupHumanReadable(EType type)
|
||||
const std::string &LLInventoryType::lookupHumanReadable(EType type)
|
||||
{
|
||||
if((type >= 0) && (type < IT_COUNT))
|
||||
{
|
||||
return INVENTORY_TYPE_HUMAN_NAMES[S32(type)];
|
||||
}
|
||||
else
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(type);
|
||||
if (!entry) return empty_string;
|
||||
return entry->mHumanName;
|
||||
}
|
||||
|
||||
// return the default inventory for the given asset type.
|
||||
|
|
@ -210,21 +171,21 @@ LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType a
|
|||
}
|
||||
}
|
||||
|
||||
bool inventory_and_asset_types_match(
|
||||
LLInventoryType::EType inventory_type,
|
||||
LLAssetType::EType asset_type)
|
||||
bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type,
|
||||
LLAssetType::EType asset_type)
|
||||
{
|
||||
bool rv = false;
|
||||
if((inventory_type >= 0) && (inventory_type < LLInventoryType::IT_COUNT))
|
||||
const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(inventory_type);
|
||||
if (!entry) return false;
|
||||
|
||||
for (InventoryEntry::asset_vec_t::const_iterator iter = entry->mAssetTypes.begin();
|
||||
iter != entry->mAssetTypes.end();
|
||||
iter++)
|
||||
{
|
||||
for(S32 i = 0; i < MAX_POSSIBLE_ASSET_TYPES; ++i)
|
||||
const LLAssetType::EType type = (*iter);
|
||||
if(type == asset_type)
|
||||
{
|
||||
if(INVENTORY_TO_ASSET_TYPE[inventory_type][i] == asset_type)
|
||||
{
|
||||
rv = true;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,25 +75,24 @@ public:
|
|||
|
||||
// machine transation between type and strings
|
||||
static EType lookup(const std::string& name);
|
||||
static const char* lookup(EType type);
|
||||
static const std::string &lookup(EType type);
|
||||
|
||||
// translation from a type to a human readable form.
|
||||
static const char* lookupHumanReadable(EType type);
|
||||
static const std::string &lookupHumanReadable(EType type);
|
||||
|
||||
// return the default inventory for the given asset type.
|
||||
static EType defaultForAssetType(LLAssetType::EType asset_type);
|
||||
|
||||
private:
|
||||
// don't instantiate or derive one of these objects
|
||||
LLInventoryType( void );
|
||||
~LLInventoryType( void );
|
||||
LLInventoryType() {}
|
||||
~LLInventoryType() {}
|
||||
};
|
||||
|
||||
// helper function which returns true if inventory type and asset type
|
||||
// helper function that returns true if inventory type and asset type
|
||||
// are potentially compatible. For example, an attachment must be an
|
||||
// object, but a wearable can be a bodypart or clothing asset.
|
||||
bool inventory_and_asset_types_match(
|
||||
LLInventoryType::EType inventory_type,
|
||||
LLAssetType::EType asset_type);
|
||||
bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type,
|
||||
LLAssetType::EType asset_type);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
std::pair<LLUUID, U64> LLLandmark::mLocalRegion;
|
||||
LLLandmark::region_map_t LLLandmark::mRegions;
|
||||
LLLandmark::region_callback_t LLLandmark::mRegionCallback;
|
||||
LLLandmark::region_callback_map_t LLLandmark::sRegionCallbackMap;
|
||||
|
||||
LLLandmark::LLLandmark() :
|
||||
mGlobalPositionKnown(false)
|
||||
|
|
@ -177,7 +177,7 @@ void LLLandmark::requestRegionHandle(
|
|||
LLMessageSystem* msg,
|
||||
const LLHost& upstream_host,
|
||||
const LLUUID& region_id,
|
||||
LLRegionHandleCallback* callback)
|
||||
region_handle_callback_t callback)
|
||||
{
|
||||
if(region_id.isNull())
|
||||
{
|
||||
|
|
@ -186,7 +186,7 @@ void LLLandmark::requestRegionHandle(
|
|||
if(callback)
|
||||
{
|
||||
const U64 U64_ZERO = 0;
|
||||
callback->dataReady(region_id, U64_ZERO);
|
||||
callback(region_id, U64_ZERO);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -196,7 +196,7 @@ void LLLandmark::requestRegionHandle(
|
|||
lldebugs << "requestRegionHandle: local" << llendl;
|
||||
if(callback)
|
||||
{
|
||||
callback->dataReady(region_id, mLocalRegion.second);
|
||||
callback(region_id, mLocalRegion.second);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -207,8 +207,8 @@ void LLLandmark::requestRegionHandle(
|
|||
lldebugs << "requestRegionHandle: upstream" << llendl;
|
||||
if(callback)
|
||||
{
|
||||
region_callback_t::value_type vt(region_id, callback);
|
||||
mRegionCallback.insert(vt);
|
||||
region_callback_map_t::value_type vt(region_id, callback);
|
||||
sRegionCallbackMap.insert(vt);
|
||||
}
|
||||
lldebugs << "Landmark requesting information about: "
|
||||
<< region_id << llendl;
|
||||
|
|
@ -221,7 +221,7 @@ void LLLandmark::requestRegionHandle(
|
|||
{
|
||||
// we have the answer locally - just call the callack.
|
||||
lldebugs << "requestRegionHandle: ready" << llendl;
|
||||
callback->dataReady(region_id, (*it).second.mRegionHandle);
|
||||
callback(region_id, (*it).second.mRegionHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -259,11 +259,11 @@ void LLLandmark::processRegionIDAndHandle(LLMessageSystem* msg, void**)
|
|||
#endif
|
||||
|
||||
// make all the callbacks here.
|
||||
region_callback_t::iterator it;
|
||||
while((it = mRegionCallback.find(region_id)) != mRegionCallback.end())
|
||||
region_callback_map_t::iterator it;
|
||||
while((it = sRegionCallbackMap.find(region_id)) != sRegionCallbackMap.end())
|
||||
{
|
||||
(*it).second->dataReady(region_id, info.mRegionHandle);
|
||||
mRegionCallback.erase(it);
|
||||
(*it).second(region_id, info.mRegionHandle);
|
||||
sRegionCallbackMap.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#define LL_LLLANDMARK_H
|
||||
|
||||
#include <map>
|
||||
#include <boost/function.hpp>
|
||||
#include "llframetimer.h"
|
||||
#include "lluuid.h"
|
||||
#include "v3dmath.h"
|
||||
|
|
@ -42,24 +43,12 @@
|
|||
class LLMessageSystem;
|
||||
class LLHost;
|
||||
|
||||
// virutal base class used for calling back interested parties when a
|
||||
// region handle comes back.
|
||||
class LLRegionHandleCallback
|
||||
{
|
||||
public:
|
||||
LLRegionHandleCallback() {}
|
||||
virtual ~LLRegionHandleCallback() {}
|
||||
virtual bool dataReady(
|
||||
const LLUUID& region_id,
|
||||
const U64& region_handle)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class LLLandmark
|
||||
{
|
||||
public:
|
||||
// for calling back interested parties when a region handle comes back.
|
||||
typedef boost::function<void(const LLUUID& region_id, const U64& region_handle)> region_handle_callback_t;
|
||||
|
||||
~LLLandmark() {}
|
||||
|
||||
// returns true if the position is known.
|
||||
|
|
@ -90,7 +79,7 @@ public:
|
|||
LLMessageSystem* msg,
|
||||
const LLHost& upstream_host,
|
||||
const LLUUID& region_id,
|
||||
LLRegionHandleCallback* callback);
|
||||
region_handle_callback_t callback);
|
||||
|
||||
// Call this method to create a lookup for this region. This
|
||||
// simplifies a lot of the code.
|
||||
|
|
@ -118,8 +107,8 @@ private:
|
|||
static std::pair<LLUUID, U64> mLocalRegion;
|
||||
typedef std::map<LLUUID, CacheInfo> region_map_t;
|
||||
static region_map_t mRegions;
|
||||
typedef std::multimap<LLUUID, LLRegionHandleCallback*> region_callback_t;
|
||||
static region_callback_t mRegionCallback;
|
||||
typedef std::multimap<LLUUID, region_handle_callback_t> region_callback_map_t;
|
||||
static region_callback_map_t sRegionCallbackMap;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ void LLParcel::init(const LLUUID &owner_id,
|
|||
mSaleTimerExpires.stop();
|
||||
mGraceExtension = 0;
|
||||
//mExpireAction = STEA_REVERT;
|
||||
mRecordTransaction = FALSE;
|
||||
//mRecordTransaction = FALSE;
|
||||
|
||||
mAuctionID = 0;
|
||||
mInEscrow = false;
|
||||
|
|
|
|||
|
|
@ -414,12 +414,6 @@ public:
|
|||
void completeSale(U32& type, U8& flags, LLUUID& to_id);
|
||||
void clearSale();
|
||||
|
||||
// this function returns TRUE if the parcel needs conversion to a
|
||||
// lease from a non-owned-status state.
|
||||
BOOL getRecordTransaction() const { return mRecordTransaction; }
|
||||
void setRecordTransaction(BOOL record) { mRecordTransaction = record; }
|
||||
|
||||
|
||||
// more accessors
|
||||
U32 getParcelFlags() const { return mParcelFlags; }
|
||||
|
||||
|
|
@ -597,8 +591,6 @@ protected:
|
|||
ELandingType mLandingType;
|
||||
LLTimer mSaleTimerExpires;
|
||||
S32 mGraceExtension;
|
||||
BOOL mRecordTransaction;
|
||||
|
||||
|
||||
// This value is non-zero if there is an auction associated with
|
||||
// the parcel.
|
||||
|
|
|
|||
|
|
@ -80,3 +80,12 @@ set_source_files_properties(${llmath_HEADER_FILES}
|
|||
list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES})
|
||||
|
||||
add_library (llmath ${llmath_SOURCE_FILES})
|
||||
|
||||
|
||||
include(LLAddBuildTest)
|
||||
SET(llmath_TEST_SOURCE_FILES
|
||||
# WARNING: Please don't write tests against LLCommon or LLMath until this issue is resolved: https://jira.lindenlab.com/jira/browse/DEV-29456
|
||||
# llvolume.cpp
|
||||
)
|
||||
LL_ADD_PROJECT_UNIT_TESTS(llmath "${llmath_TEST_SOURCE_FILES}")
|
||||
|
||||
|
|
|
|||
|
|
@ -64,17 +64,11 @@ public:
|
|||
mLeft(left), mTop(top), mRight(right), mBottom(bottom)
|
||||
{}
|
||||
|
||||
LLRectBase(const LLSD& sd)
|
||||
explicit LLRectBase(const LLSD& sd)
|
||||
{
|
||||
setValue(sd);
|
||||
}
|
||||
|
||||
const LLRectBase& operator=(const LLSD& sd)
|
||||
{
|
||||
setValue(sd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void setValue(const LLSD& sd)
|
||||
{
|
||||
mLeft = sd[0].asInteger();
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ public:
|
|||
// whatever calls getVolume() never owns the LLVolume* and
|
||||
// cannot keep references for long since it may be deleted
|
||||
// later. For best results hold it in an LLPointer<LLVolume>.
|
||||
LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail);
|
||||
void unrefVolume(LLVolume *volumep);
|
||||
virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail);
|
||||
virtual void unrefVolume(LLVolume *volumep);
|
||||
|
||||
void dump();
|
||||
|
||||
|
|
|
|||
|
|
@ -75,6 +75,42 @@ std::ostream& operator<<(std::ostream& s, const LLColor3 &a)
|
|||
return s;
|
||||
}
|
||||
|
||||
static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
|
||||
{
|
||||
if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
|
||||
if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
|
||||
if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
|
||||
if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
|
||||
if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
|
||||
return ( val1In );
|
||||
}
|
||||
|
||||
void LLColor3::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn)
|
||||
{
|
||||
if ( sValIn < 0.00001f )
|
||||
{
|
||||
mV[VRED] = lValIn;
|
||||
mV[VGREEN] = lValIn;
|
||||
mV[VBLUE] = lValIn;
|
||||
}
|
||||
else
|
||||
{
|
||||
F32 interVal1;
|
||||
F32 interVal2;
|
||||
|
||||
if ( lValIn < 0.5f )
|
||||
interVal2 = lValIn * ( 1.0f + sValIn );
|
||||
else
|
||||
interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
|
||||
|
||||
interVal1 = 2.0f * lValIn - interVal2;
|
||||
|
||||
mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
|
||||
mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn );
|
||||
mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
|
||||
}
|
||||
}
|
||||
|
||||
void LLColor3::calcHSL(F32* hue, F32* saturation, F32* luminance) const
|
||||
{
|
||||
F32 var_R = mV[VRED];
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ public:
|
|||
mV[2] = (F32) sd[2].asReal();;
|
||||
}
|
||||
|
||||
void setHSL(F32 hue, F32 saturation, F32 luminance);
|
||||
void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
|
||||
|
||||
const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0)
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ class LLVector3d
|
|||
inline LLVector3d(const F64 x, const F64 y, const F64 z); // Initializes LLVector3d to (x. y, z)
|
||||
inline explicit LLVector3d(const F64 *vec); // Initializes LLVector3d to (vec[0]. vec[1], vec[2])
|
||||
inline explicit LLVector3d(const LLVector3 &vec);
|
||||
LLVector3d(const LLSD& sd)
|
||||
explicit LLVector3d(const LLSD& sd)
|
||||
{
|
||||
setValue(sd);
|
||||
}
|
||||
|
|
@ -65,12 +65,6 @@ class LLVector3d
|
|||
mdV[2] = sd[2].asReal();
|
||||
}
|
||||
|
||||
const LLVector3d& operator=(const LLSD& sd)
|
||||
{
|
||||
setValue(sd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLSD getValue() const
|
||||
{
|
||||
LLSD ret;
|
||||
|
|
|
|||
|
|
@ -314,12 +314,6 @@ void LLVector3::setValue(const LLSD& sd)
|
|||
mV[2] = (F32) sd[2].asReal();
|
||||
}
|
||||
|
||||
const LLVector3& LLVector3::operator=(const LLSD& sd)
|
||||
{
|
||||
setValue(sd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot)
|
||||
{
|
||||
const F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ];
|
||||
|
|
|
|||
|
|
@ -67,14 +67,12 @@ class LLVector3
|
|||
explicit LLVector3(const LLVector2 &vec); // Initializes LLVector3 to (vec[0]. vec[1], 0)
|
||||
explicit LLVector3(const LLVector3d &vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2])
|
||||
explicit LLVector3(const LLVector4 &vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2])
|
||||
LLVector3(const LLSD& sd);
|
||||
explicit LLVector3(const LLSD& sd);
|
||||
|
||||
LLSD getValue() const;
|
||||
|
||||
void setValue(const LLSD& sd);
|
||||
|
||||
const LLVector3& operator=(const LLSD& sd);
|
||||
|
||||
inline BOOL isFinite() const; // checks to see if all values of LLVector3 are finite
|
||||
BOOL clamp(F32 min, F32 max); // Clamps all values to (min,max), returns TRUE if data changed
|
||||
BOOL clampLength( F32 length_limit ); // Scales vector to limit length to a value
|
||||
|
|
|
|||
|
|
@ -305,6 +305,42 @@ LLColor4 vec3to4(const LLColor3 &vec)
|
|||
return temp;
|
||||
}
|
||||
|
||||
static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
|
||||
{
|
||||
if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
|
||||
if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
|
||||
if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
|
||||
if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
|
||||
if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
|
||||
return ( val1In );
|
||||
}
|
||||
|
||||
void LLColor4::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn)
|
||||
{
|
||||
if ( sValIn < 0.00001f )
|
||||
{
|
||||
mV[VRED] = lValIn;
|
||||
mV[VGREEN] = lValIn;
|
||||
mV[VBLUE] = lValIn;
|
||||
}
|
||||
else
|
||||
{
|
||||
F32 interVal1;
|
||||
F32 interVal2;
|
||||
|
||||
if ( lValIn < 0.5f )
|
||||
interVal2 = lValIn * ( 1.0f + sValIn );
|
||||
else
|
||||
interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
|
||||
|
||||
interVal1 = 2.0f * lValIn - interVal2;
|
||||
|
||||
mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
|
||||
mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn );
|
||||
mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
|
||||
}
|
||||
}
|
||||
|
||||
void LLColor4::calcHSL(F32* hue, F32* saturation, F32* luminance) const
|
||||
{
|
||||
F32 var_R = mV[VRED];
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class LLColor4
|
|||
LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc))
|
||||
LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1)
|
||||
LLColor4(const LLColor3 &vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a)
|
||||
LLColor4(const LLSD& sd);
|
||||
explicit LLColor4(const LLSD& sd);
|
||||
explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion
|
||||
explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion
|
||||
|
||||
|
|
@ -74,6 +74,7 @@ class LLColor4
|
|||
|
||||
void setValue(const LLSD& sd);
|
||||
|
||||
void setHSL(F32 hue, F32 saturation, F32 luminance);
|
||||
void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
|
||||
|
||||
const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1)
|
||||
|
|
@ -112,7 +113,6 @@ class LLColor4
|
|||
F32 &operator[](int idx) { return mV[idx]; }
|
||||
|
||||
const LLColor4& operator=(const LLColor3 &a); // Assigns vec3 to vec4 and returns vec4
|
||||
const LLColor4& operator=(const LLSD& sd);
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a
|
||||
friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b
|
||||
|
|
@ -633,12 +633,5 @@ void LLColor4::clamp()
|
|||
}
|
||||
}
|
||||
|
||||
inline const LLColor4& LLColor4::operator=(const LLSD& sd)
|
||||
{
|
||||
setValue(sd);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public:
|
|||
LLColor4U(U8 r, U8 g, U8 b); // Initializes LLColor4U to (r, g, b, 1)
|
||||
LLColor4U(U8 r, U8 g, U8 b, U8 a); // Initializes LLColor4U to (r. g, b, a)
|
||||
LLColor4U(const U8 *vec); // Initializes LLColor4U to (vec[0]. vec[1], vec[2], 1)
|
||||
LLColor4U(const LLSD& sd)
|
||||
explicit LLColor4U(const LLSD& sd)
|
||||
{
|
||||
setValue(sd);
|
||||
}
|
||||
|
|
@ -79,12 +79,6 @@ public:
|
|||
mV[3] = sd[3].asInteger();
|
||||
}
|
||||
|
||||
const LLColor4U& operator=(const LLSD& sd)
|
||||
{
|
||||
setValue(sd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LLSD getValue() const
|
||||
{
|
||||
LLSD ret;
|
||||
|
|
|
|||
|
|
@ -219,10 +219,15 @@ IF (NOT LINUX AND VIEWER)
|
|||
# When building the viewer the tests links against the shared objects.
|
||||
# These can not be found when we try to run the tests, so we had to disable them, for the viewer build.
|
||||
# TODO: Can someone with viewer knowledge figure out how to make these find the correct so.
|
||||
#ADD_BUILD_TEST(llhttpclientadapter llmessage)
|
||||
ADD_BUILD_TEST(lltrustedmessageservice llmessage)
|
||||
ADD_BUILD_TEST(lltemplatemessagedispatcher llmessage)
|
||||
SET(llmessage_TEST_SOURCE_FILES
|
||||
# llhttpclientadapter.cpp
|
||||
lltrustedmessageservice.cpp
|
||||
lltemplatemessagedispatcher.cpp
|
||||
)
|
||||
LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
|
||||
|
||||
# Commented out - see rationale at bottom of newview's build file + poppy 2009-06-05
|
||||
# Don't make llmessage depend on llsdmessage_test because ADD_COMM_BUILD_TEST depends on llmessage!
|
||||
ADD_COMM_BUILD_TEST(llsdmessage "" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py")
|
||||
# ADD_COMM_BUILD_TEST(llsdmessage "" "${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py")
|
||||
ADD_BUILD_TEST(llareslistener llmessage)
|
||||
ENDIF (NOT LINUX AND VIEWER)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "llsdserialize.h"
|
||||
#include "lluuid.h"
|
||||
#include "message.h"
|
||||
#include "llmemtype.h"
|
||||
|
||||
// llsd serialization constants
|
||||
static const std::string AGENTS("agents");
|
||||
|
|
@ -607,6 +608,7 @@ boost::signals2::connection LLCacheName::get(const LLUUID& id, BOOL is_group, ol
|
|||
|
||||
void LLCacheName::processPending()
|
||||
{
|
||||
LLMemType mt_pp(LLMemType::MTYPE_CACHE_PROCESS_PENDING);
|
||||
const F32 SECS_BETWEEN_PROCESS = 0.1f;
|
||||
if(!impl.mProcessTimer.checkExpirationAndReset(SECS_BETWEEN_PROCESS))
|
||||
{
|
||||
|
|
@ -700,6 +702,7 @@ std::string LLCacheName::getDefaultName()
|
|||
|
||||
void LLCacheName::Impl::processPendingAsks()
|
||||
{
|
||||
LLMemType mt_ppa(LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS);
|
||||
sendRequest(_PREHASH_UUIDNameRequest, mAskNameQueue);
|
||||
sendRequest(_PREHASH_UUIDGroupNameRequest, mAskGroupQueue);
|
||||
mAskNameQueue.clear();
|
||||
|
|
@ -708,6 +711,7 @@ void LLCacheName::Impl::processPendingAsks()
|
|||
|
||||
void LLCacheName::Impl::processPendingReplies()
|
||||
{
|
||||
LLMemType mt_ppr(LLMemType::MTYPE_CACHE_PROCESS_PENDING_REPLIES);
|
||||
// First call all the callbacks, because they might send messages.
|
||||
for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -224,6 +224,10 @@ static void request(
|
|||
LLURLRequest* req = new LLURLRequest(method, url);
|
||||
req->checkRootCertificate(true);
|
||||
|
||||
|
||||
lldebugs << LLURLRequest::actionAsVerb(method) << " " << url << " "
|
||||
<< headers << llendl;
|
||||
|
||||
// Insert custom headers is the caller sent any
|
||||
if (headers.isMap())
|
||||
{
|
||||
|
|
@ -375,72 +379,140 @@ private:
|
|||
std::string mBuffer;
|
||||
};
|
||||
|
||||
// *TODO: Deprecate (only used by dataserver)
|
||||
// This call is blocking! This is probably usually bad. :(
|
||||
LLSD LLHTTPClient::blockingGet(const std::string& url)
|
||||
// These calls are blocking! This is usually bad, unless you're a dataserver. Then it's awesome.
|
||||
|
||||
/**
|
||||
@brief does a blocking request on the url, returning the data or bad status.
|
||||
|
||||
@param url URI to verb on.
|
||||
@param method the verb to hit the URI with.
|
||||
@param body the body of the call (if needed - for instance not used for GET and DELETE, but is for POST and PUT)
|
||||
@param headers HTTP headers to use for the request.
|
||||
@param timeout Curl timeout to use. Defaults to 5. Rationale:
|
||||
Without this timeout, blockingGet() calls have been observed to take
|
||||
up to 90 seconds to complete. Users of blockingGet() already must
|
||||
check the HTTP return code for validity, so this will not introduce
|
||||
new errors. A 5 second timeout will succeed > 95% of the time (and
|
||||
probably > 99% of the time) based on my statistics. JC
|
||||
|
||||
@returns an LLSD map: {status: integer, body: map}
|
||||
*/
|
||||
static LLSD blocking_request(
|
||||
const std::string& url,
|
||||
LLURLRequest::ERequestAction method,
|
||||
const LLSD& body,
|
||||
const LLSD& headers = LLSD(),
|
||||
const F32 timeout = 5
|
||||
)
|
||||
{
|
||||
llinfos << "blockingGet of " << url << llendl;
|
||||
|
||||
// Returns an LLSD map: {status: integer, body: map}
|
||||
char curl_error_buffer[CURL_ERROR_SIZE];
|
||||
lldebugs << "blockingRequest of " << url << llendl;
|
||||
char curl_error_buffer[CURL_ERROR_SIZE] = "\0";
|
||||
CURL* curlp = curl_easy_init();
|
||||
|
||||
LLHTTPBuffer http_buffer;
|
||||
|
||||
// Without this timeout, blockingGet() calls have been observed to take
|
||||
// up to 90 seconds to complete. Users of blockingGet() already must
|
||||
// check the HTTP return code for validity, so this will not introduce
|
||||
// new errors. A 5 second timeout will succeed > 95% of the time (and
|
||||
// probably > 99% of the time) based on my statistics. JC
|
||||
std::string body_str;
|
||||
|
||||
// other request method checks root cert first, we skip?
|
||||
//req->checkRootCertificate(true);
|
||||
|
||||
// * Set curl handle options
|
||||
curl_easy_setopt(curlp, CURLOPT_NOSIGNAL, 1); // don't use SIGALRM for timeouts
|
||||
curl_easy_setopt(curlp, CURLOPT_TIMEOUT, 5); // seconds
|
||||
|
||||
curl_easy_setopt(curlp, CURLOPT_TIMEOUT, timeout); // seconds, see warning at top of function.
|
||||
curl_easy_setopt(curlp, CURLOPT_WRITEFUNCTION, LLHTTPBuffer::curl_write);
|
||||
curl_easy_setopt(curlp, CURLOPT_WRITEDATA, &http_buffer);
|
||||
curl_easy_setopt(curlp, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curlp, CURLOPT_ERRORBUFFER, curl_error_buffer);
|
||||
curl_easy_setopt(curlp, CURLOPT_FAILONERROR, 1);
|
||||
|
||||
// * Setup headers (don't forget to free them after the call!)
|
||||
curl_slist* headers_list = NULL;
|
||||
if (headers.isMap())
|
||||
{
|
||||
LLSD::map_const_iterator iter = headers.beginMap();
|
||||
LLSD::map_const_iterator end = headers.endMap();
|
||||
for (; iter != end; ++iter)
|
||||
{
|
||||
std::ostringstream header;
|
||||
header << iter->first << ": " << iter->second.asString() ;
|
||||
lldebugs << "header = " << header.str() << llendl;
|
||||
headers_list = curl_slist_append(headers_list, header.str().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// * Setup specific method / "verb" for the URI (currently only GET and POST supported + poppy)
|
||||
if (method == LLURLRequest::HTTP_GET)
|
||||
{
|
||||
curl_easy_setopt(curlp, CURLOPT_HTTPGET, 1);
|
||||
}
|
||||
else if (method == LLURLRequest::HTTP_POST)
|
||||
{
|
||||
curl_easy_setopt(curlp, CURLOPT_POST, 1);
|
||||
//serialize to ostr then copy to str - need to because ostr ptr is unstable :(
|
||||
std::ostringstream ostr;
|
||||
LLSDSerialize::toXML(body, ostr);
|
||||
body_str = ostr.str();
|
||||
curl_easy_setopt(curlp, CURLOPT_POSTFIELDS, body_str.c_str());
|
||||
//copied from PHP libs, correct?
|
||||
headers_list = curl_slist_append(headers_list, "Content-Type: application/llsd+xml");
|
||||
|
||||
struct curl_slist *header_list = NULL;
|
||||
header_list = curl_slist_append(header_list, "Accept: application/llsd+xml");
|
||||
CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, header_list);
|
||||
// copied from llurlrequest.cpp
|
||||
// it appears that apache2.2.3 or django in etch is busted. If
|
||||
// we do not clear the expect header, we get a 500. May be
|
||||
// limited to django/mod_wsgi.
|
||||
headers_list = curl_slist_append(headers_list, "Expect:");
|
||||
}
|
||||
|
||||
// * Do the action using curl, handle results
|
||||
lldebugs << "HTTP body: " << body_str << llendl;
|
||||
headers_list = curl_slist_append(headers_list, "Accept: application/llsd+xml");
|
||||
CURLcode curl_result = curl_easy_setopt(curlp, CURLOPT_HTTPHEADER, headers_list);
|
||||
if ( curl_result != CURLE_OK )
|
||||
{
|
||||
llinfos << "Curl is hosed - can't add Accept header for llsd+xml" << llendl;
|
||||
llinfos << "Curl is hosed - can't add headers" << llendl;
|
||||
}
|
||||
|
||||
LLSD response = LLSD::emptyMap();
|
||||
|
||||
S32 curl_success = curl_easy_perform(curlp);
|
||||
|
||||
S32 http_status = 499;
|
||||
curl_easy_getinfo(curlp,CURLINFO_RESPONSE_CODE, &http_status);
|
||||
|
||||
curl_easy_getinfo(curlp, CURLINFO_RESPONSE_CODE, &http_status);
|
||||
response["status"] = http_status;
|
||||
|
||||
if (curl_success != 0
|
||||
&& http_status != 404) // We expect 404s, don't spam for them.
|
||||
// if we get a non-404 and it's not a 200 OR maybe it is but you have error bits,
|
||||
if ( http_status != 404 && (http_status != 200 || curl_success != 0) )
|
||||
{
|
||||
// We expect 404s, don't spam for them.
|
||||
llwarns << "CURL REQ URL: " << url << llendl;
|
||||
llwarns << "CURL REQ METHOD TYPE: " << method << llendl;
|
||||
llwarns << "CURL REQ HEADERS: " << headers.asString() << llendl;
|
||||
llwarns << "CURL REQ BODY: " << body_str << llendl;
|
||||
llwarns << "CURL HTTP_STATUS: " << http_status << llendl;
|
||||
llwarns << "CURL ERROR: " << curl_error_buffer << llendl;
|
||||
|
||||
llwarns << "CURL ERROR BODY: " << http_buffer.asString() << llendl;
|
||||
response["body"] = http_buffer.asString();
|
||||
}
|
||||
else
|
||||
{
|
||||
response["body"] = http_buffer.asLLSD();
|
||||
lldebugs << "CURL response: " << http_buffer.asString() << llendl;
|
||||
}
|
||||
|
||||
if(header_list)
|
||||
if(headers_list)
|
||||
{ // free the header list
|
||||
curl_slist_free_all(header_list);
|
||||
header_list = NULL;
|
||||
curl_slist_free_all(headers_list);
|
||||
}
|
||||
|
||||
// * Cleanup
|
||||
curl_easy_cleanup(curlp);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
LLSD LLHTTPClient::blockingGet(const std::string& url)
|
||||
{
|
||||
return blocking_request(url, LLURLRequest::HTTP_GET, LLSD());
|
||||
}
|
||||
|
||||
LLSD LLHTTPClient::blockingPost(const std::string& url, const LLSD& body)
|
||||
{
|
||||
return blocking_request(url, LLURLRequest::HTTP_POST, body);
|
||||
}
|
||||
|
||||
void LLHTTPClient::put(
|
||||
const std::string& url,
|
||||
const LLSD& body,
|
||||
|
|
|
|||
|
|
@ -142,6 +142,14 @@ public:
|
|||
*/
|
||||
static LLSD blockingGet(const std::string& url);
|
||||
|
||||
/**
|
||||
* @brief Blocking HTTP POST that returns an LLSD map of status and body.
|
||||
*
|
||||
* @param url the complete serialized (and escaped) url to get
|
||||
* @param body the LLSD post body
|
||||
* @return An LLSD of { 'status':status (an int), 'body':payload (an LLSD) }
|
||||
*/
|
||||
static LLSD blockingPost(const std::string& url, const LLSD& body);
|
||||
|
||||
|
||||
static void setPump(LLPumpIO& pump);
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ LLPointer<LLIMInfo> llsd_to_im_info(const LLSD& im_info_sd)
|
|||
param_message["message"].asString(),
|
||||
param_message["id"].asUUID(),
|
||||
(U32) param_message["parent_estate_id"].asInteger(),
|
||||
im_info->mRegionID = param_message["region_id"].asUUID(),
|
||||
param_message["region_id"].asUUID(),
|
||||
ll_vector3_from_sd(param_message["position"]),
|
||||
param_message["data"],
|
||||
(U8) param_message["offline"].asInteger(),
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ public:
|
|||
static LLMessageConfigFile& instance();
|
||||
// return the singleton configuration file
|
||||
|
||||
/* virtual */ void loadFile();
|
||||
/* virtual */ bool loadFile();
|
||||
void loadServerDefaults(const LLSD& data);
|
||||
void loadMaxQueuedEvents(const LLSD& data);
|
||||
void loadMessages(const LLSD& data);
|
||||
|
|
@ -98,7 +98,7 @@ LLMessageConfigFile& LLMessageConfigFile::instance()
|
|||
}
|
||||
|
||||
// virtual
|
||||
void LLMessageConfigFile::loadFile()
|
||||
bool LLMessageConfigFile::loadFile()
|
||||
{
|
||||
LLSD data;
|
||||
{
|
||||
|
|
@ -115,7 +115,7 @@ void LLMessageConfigFile::loadFile()
|
|||
LL_INFOS("AppInit") << "LLMessageConfigFile::loadFile: file missing,"
|
||||
" ill-formed, or simply undefined; not changing the"
|
||||
" file" << LL_ENDL;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
loadServerDefaults(data);
|
||||
|
|
@ -123,6 +123,7 @@ void LLMessageConfigFile::loadFile()
|
|||
loadMessages(data);
|
||||
loadCapBans(data);
|
||||
loadMessageBans(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLMessageConfigFile::loadServerDefaults(const LLSD& data)
|
||||
|
|
|
|||
|
|
@ -98,6 +98,26 @@ LLURLRequestDetail::~LLURLRequestDetail()
|
|||
* class LLURLRequest
|
||||
*/
|
||||
|
||||
// static
|
||||
std::string LLURLRequest::actionAsVerb(LLURLRequest::ERequestAction action)
|
||||
{
|
||||
static const std::string VERBS[] =
|
||||
{
|
||||
"(invalid)",
|
||||
"HEAD",
|
||||
"GET",
|
||||
"PUT",
|
||||
"POST",
|
||||
"DELETE",
|
||||
"MOVE"
|
||||
};
|
||||
if(((S32)action <=0) || ((S32)action >= REQUEST_ACTION_COUNT))
|
||||
{
|
||||
return VERBS[0];
|
||||
}
|
||||
return VERBS[action];
|
||||
}
|
||||
|
||||
LLURLRequest::LLURLRequest(LLURLRequest::ERequestAction action) :
|
||||
mAction(action)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -81,6 +81,11 @@ public:
|
|||
REQUEST_ACTION_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Turn the requst action into an http verb.
|
||||
*/
|
||||
static std::string actionAsVerb(ERequestAction action);
|
||||
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@
|
|||
#include "v3math.h"
|
||||
#include "v4math.h"
|
||||
#include "lltransfertargetvfile.h"
|
||||
#include "llmemtype.h"
|
||||
|
||||
// Constants
|
||||
//const char* MESSAGE_LOG_FILENAME = "message.log";
|
||||
|
|
@ -794,6 +795,7 @@ S32 LLMessageSystem::getReceiveBytes() const
|
|||
|
||||
void LLMessageSystem::processAcks()
|
||||
{
|
||||
LLMemType mt_pa(LLMemType::MTYPE_MESSAGE_PROCESS_ACKS);
|
||||
F64 mt_sec = getMessageTimeSeconds();
|
||||
{
|
||||
gTransferManager.updateTransfers();
|
||||
|
|
@ -4020,6 +4022,7 @@ void LLMessageSystem::setTimeDecodesSpamThreshold( F32 seconds )
|
|||
// TODO: babbage: move gServicePump in to LLMessageSystem?
|
||||
bool LLMessageSystem::checkAllMessages(S64 frame_count, LLPumpIO* http_pump)
|
||||
{
|
||||
LLMemType mt_cam(LLMemType::MTYPE_MESSAGE_CHECK_ALL);
|
||||
if(checkMessages(frame_count))
|
||||
{
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -509,6 +509,22 @@ private:
|
|||
public:
|
||||
// BOOL decodeData(const U8 *buffer, const LLHost &host);
|
||||
|
||||
/**
|
||||
gets binary data from the current message.
|
||||
|
||||
@param blockname the name of the block in the message (from the message template)
|
||||
|
||||
@param varname
|
||||
|
||||
@param datap
|
||||
|
||||
@param size expected size - set to zero to get any amount of data up to max_size.
|
||||
Make sure max_size is set in that case!
|
||||
|
||||
@param blocknum
|
||||
|
||||
@param max_size the max number of bytes to read
|
||||
*/
|
||||
void getBinaryDataFast(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX);
|
||||
void getBinaryData(const char *blockname, const char *varname, void *datap, S32 size, S32 blocknum = 0, S32 max_size = S32_MAX);
|
||||
void getBOOLFast( const char *block, const char *var, BOOL &data, S32 blocknum = 0);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* @file llcurl_stub.cpp
|
||||
* @brief stub class to allow unit testing
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=internal$
|
||||
* $LicenseInfo:firstyear=2008&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2008-2009, Linden Research, Inc.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* @file
|
||||
* @brief
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=internal$
|
||||
* $LicenseInfo:firstyear=2008&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2008-2009, Linden Research, Inc.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* @file
|
||||
* @brief
|
||||
*
|
||||
* $LicenseInfo:firstyear=2008&license=internal$
|
||||
* $LicenseInfo:firstyear=2008&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2008-2009, Linden Research, Inc.
|
||||
*
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue