Merge with viewer-2.0.0-3 branch

master
Bryan O'Sullivan 2009-06-22 15:02:19 -07:00
commit baa73fddd9
1172 changed files with 131801 additions and 86499 deletions

View File

@ -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

View File

@ -1,3 +1,4 @@
# -*- cmake -*-
# cmake_minimum_required should appear before any

View File

@ -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"

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -42,6 +42,7 @@ if (WINDOWS)
wldap32
gdi32
user32
dbghelp
)
else (WINDOWS)
set(WINDOWS_LIBRARIES "")

View File

@ -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)

View File

@ -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(

View File

@ -62,6 +62,7 @@ endif (DARWIN)
target_link_libraries(llui_libtest
llui
${OS_LIBRARIES}
${GOOGLE_PERFTOOLS_LIBRARIES}
)
if (WINDOWS)

View File

@ -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;

View File

@ -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");
}

View File

@ -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:

View File

@ -10,7 +10,7 @@ values = (
'&<>',
u'\u81acj',
llsd.uri('http://foo<'),
lluuid.LLUUID(),
lluuid.UUID(),
llsd.LLSD(['thing']),
1,
myint(31337),

View File

@ -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])

View File

@ -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()

View File

@ -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.

View File

@ -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)

View File

@ -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:

View File

@ -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; }

View File

@ -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() );

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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);

View File

@ -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

View File

@ -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));
}

View File

@ -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

View File

@ -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
{

View File

@ -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;
};

View File

@ -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

View File

@ -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

View File

@ -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 ;

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;

View File

@ -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)

View File

@ -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();

View File

@ -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];
}

View File

@ -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;
};
//----------------------------------------------------------------------------

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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();

View File

@ -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;
};
/**

View File

@ -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)
{

View File

@ -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);

View File

@ -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";

View File

@ -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

View File

@ -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";
}

View File

@ -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
};

View File

@ -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");
}
};

View File

@ -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

View File

@ -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();

View File

@ -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;
};

View File

@ -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();

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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}")

View File

@ -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();

View File

@ -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();

View File

@ -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];

View File

@ -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)

View File

@ -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;

View File

@ -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];

View File

@ -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

View File

@ -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];

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -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)
{

View File

@ -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,

View File

@ -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);

View File

@ -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(),

View File

@ -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)

View File

@ -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)
{

View File

@ -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.
*

View File

@ -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;

View File

@ -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);

View File

@ -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.
*

View File

@ -2,7 +2,7 @@
* @file
* @brief
*
* $LicenseInfo:firstyear=2008&license=internal$
* $LicenseInfo:firstyear=2008&license=viewergpl$
*
* Copyright (c) 2008-2009, Linden Research, Inc.
*

View File

@ -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