diff --git a/etc/message.xml b/etc/message.xml index 690103bb7..1665b0017 100644 --- a/etc/message.xml +++ b/etc/message.xml @@ -378,14 +378,7 @@ true - ParcelMediaURLFilter - - flavor - llsd - trusted-sender - false - - + ParcelNavigateMedia flavor diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index d01c74eaa..2bd5a9c30 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -90,26 +90,26 @@ if (WINDOWS) endif (MSVC80 OR MSVC90 OR MSVC10) # Are we using the crummy Visual Studio KDU build workaround? - if (NOT VS_DISABLE_FATAL_WARNINGS) + if (NOT DISABLE_FATAL_WARNINGS) add_definitions(/WX) - endif (NOT VS_DISABLE_FATAL_WARNINGS) + endif (NOT DISABLE_FATAL_WARNINGS) # Various libs are compiler specific, generate some variables here we can just use # when we require them instead of reimplementing the test each time. if (MSVC71) - set(MSVC_DIR 7.1) - set(MSVC_SUFFIX 71) - elseif (MSVC80) - set(MSVC_DIR 8.0) - set(MSVC_SUFFIX 80) - elseif (MSVC90) - set(MSVC_DIR 9.0) - set(MSVC_SUFFIX 90) - elseif (MSVC10) - set(MSVC_DIR 10.0) - set(MSVC_SUFFIX 100) - endif (MSVC71) + set(MSVC_DIR 7.1) + set(MSVC_SUFFIX 71) + elseif (MSVC80) + set(MSVC_DIR 8.0) + set(MSVC_SUFFIX 80) + elseif (MSVC90) + set(MSVC_DIR 9.0) + set(MSVC_SUFFIX 90) + elseif (MSVC10) + set(MSVC_DIR 10.0) + set(MSVC_SUFFIX 100) + endif (MSVC71) if (MSVC10) SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /MANIFEST:NO") @@ -125,103 +125,151 @@ set (GCC_EXTRA_OPTIMIZATIONS "-ffast-math") if (LINUX) set(CMAKE_SKIP_RPATH TRUE) - # Here's a giant hack for Fedora 8, where we can't use - # _FORTIFY_SOURCE if we're using a compiler older than gcc 4.1. - - find_program(GXX g++) - mark_as_advanced(GXX) - - if (GXX) - execute_process( - COMMAND ${GXX} --version - COMMAND sed "s/^[gc+ ]*//" - COMMAND head -1 - OUTPUT_VARIABLE GXX_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE - ) - else (GXX) - set(GXX_VERSION x) - endif (GXX) - - # The quoting hack here is necessary in case we're using distcc or - # ccache as our compiler. CMake doesn't pass the command line - # through the shell by default, so we end up trying to run "distcc" - # " g++" - notice the leading space. Ugh. - - execute_process( - COMMAND sh -c "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} --version" - COMMAND sed "s/^[gc+ ]*//" - COMMAND head -1 - OUTPUT_VARIABLE CXX_VERSION - OUTPUT_STRIP_TRAILING_WHITESPACE) - - if (${GXX_VERSION} STREQUAL ${CXX_VERSION}) - add_definitions(-D_FORTIFY_SOURCE=2) - else (${GXX_VERSION} STREQUAL ${CXX_VERSION}) - if (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat") - add_definitions(-D_FORTIFY_SOURCE=2) - endif (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat") - endif (${GXX_VERSION} STREQUAL ${CXX_VERSION}) - - #Lets actually get a numerical version of gxx's version - STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION ${CXX_VERSION}) - - #gcc 4.3 and above don't like the LL boost - if(${CXX_VERSION} GREATER 429) - add_definitions(-Wno-parentheses) - endif (${CXX_VERSION} GREATER 429) - - #gcc 4.6 has a new spammy warning - if(NOT ${CXX_VERSION} LESS 460) - add_definitions(-Wno-unused-but-set-variable) - endif (NOT ${CXX_VERSION} LESS 460) - - # End of hacks. - add_definitions( -DLL_LINUX=1 + -DAPPID=secondlife -D_REENTRANT -fexceptions -fno-math-errno -fno-strict-aliasing -fsigned-char + -fvisibility=hidden -g -pthread ) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") + # Don't catch SIGCHLD in our base application class for the viewer + # some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! + # The viewer doesn't need to catch SIGCHLD anyway. + add_definitions(-DLL_IGNORE_SIGCHLD) + + if(${CMAKE_C_COMPILER} MATCHES "gcc*") + + find_program(GXX g++) + mark_as_advanced(GXX) + + if (GXX) + execute_process( + COMMAND ${GXX} --version + COMMAND sed "s/^[gc+ ]*//" + COMMAND head -1 + OUTPUT_VARIABLE GXX_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + else (GXX) + set(GXX_VERSION x) + endif (GXX) + + # The quoting hack here is necessary in case we're using distcc or + # ccache as our compiler. CMake doesn't pass the command line + # through the shell by default, so we end up trying to run "distcc" + # " g++" - notice the leading space. Ugh. + + execute_process( + COMMAND sh -c "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} --version" + COMMAND sed "s/^[gc+ ]*//" + COMMAND head -1 + OUTPUT_VARIABLE CXX_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + + # Here's a giant hack for Fedora 8, where we can't use + # _FORTIFY_SOURCE if we're using a compiler older than gcc 4.1. + if (${GXX_VERSION} STREQUAL ${CXX_VERSION}) + add_definitions(-D_FORTIFY_SOURCE=2) + else (${GXX_VERSION} STREQUAL ${CXX_VERSION}) + if (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat") + add_definitions(-D_FORTIFY_SOURCE=2) + endif (NOT ${GXX_VERSION} MATCHES " 4.1.*Red Hat") + endif (${GXX_VERSION} STREQUAL ${CXX_VERSION}) + + #Lets actually get a numerical version of gxx's version + STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION ${CXX_VERSION}) + + #gcc 4.3 and above doesn't like the LL boost + if(${CXX_VERSION} GREATER 429) + add_definitions(-Wno-parentheses) + endif (${CXX_VERSION} GREATER 429) + + #gcc 4.6 has a new spammy warning + if(NOT ${CXX_VERSION} LESS 460) + add_definitions(-Wno-unused-but-set-variable) + endif (NOT ${CXX_VERSION} LESS 460) + + # End of hacks. + + #GCC Specific + add_definitions(-DCC_GCC) + + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99") - add_definitions(-DAPPID=secondlife) - add_definitions(-fvisibility=hidden) - # don't catch SIGCHLD in our base application class for the viewer - some of our 3rd party libs may need their *own* SIGCHLD handler to work. Sigh! The viewer doesn't need to catch SIGCHLD anyway. - add_definitions(-DLL_IGNORE_SIGCHLD) - if (NOT STANDALONE) - # this stops us requiring a really recent glibc at runtime - add_definitions(-fno-stack-protector) - endif (NOT STANDALONE) - if (${ARCH} STREQUAL "x86_64") - add_definitions(-DLINUX64=1 -pipe) - set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") - set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") - else (${ARCH} STREQUAL "x86_64") if (NOT STANDALONE) - set(MARCH_FLAG " -march=pentium4") + # this stops us requiring a really recent glibc at runtime + add_definitions(-fno-stack-protector) endif (NOT STANDALONE) - set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - endif (${ARCH} STREQUAL "x86_64") + if (${ARCH} STREQUAL "x86_64") + add_definitions(-DLINUX64=1 -pipe) + set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") + else (${ARCH} STREQUAL "x86_64") + if (NOT STANDALONE) + set(MARCH_FLAG " -march=pentium4") + endif (NOT STANDALONE) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") + set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse,387 -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + endif (${ARCH} STREQUAL "x86_64") + elseif(${CMAKE_C_COMPILER} MATCHES "clang*") + + find_program(CLANG clang++) + mark_as_advanced(CLANG) - set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG} -msse2") + add_definitions( + -DCC_CLANG + -D_FORTIFY_SOURCE=2 + -Wno-tautological-compare + -Wno-char-subscripts + -Wno-gnu + -Wno-logical-op-parentheses + -Wno-parentheses-equality + -Wno-unused-function + -Wno-unused-value + -Wno-unused-variable + ) + + if(NOT DISABLE_FATAL_WARNINGS) + add_definitions(-Werror) + endif(NOT DISABLE_FATAL_WARNINGS) + + if (NOT STANDALONE) + # this stops us requiring a really recent glibc at runtime + add_definitions(-fno-stack-protector) + endif (NOT STANDALONE) + + if (NOT STANDALONE) + set(MARCH_FLAG " -march=pentium4") + endif (NOT STANDALONE) + + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}${MARCH_FLAG} -fno-inline -msse2") + set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2}${MARCH_FLAG} -msse2") + set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2}${MARCH_FLAG} -msse2") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -msse2") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -msse2") + endif() + + set(CMAKE_CXX_FLAGS_DEBUG "-O0 ${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_C_FLAGS_DEBUG "-O0 ${CMAKE_CXX_FLAGS_DEBUG}") set(CMAKE_CXX_FLAGS_RELEASE "-O3 ${CMAKE_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS_RELEASE "-O3 ${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_RELEASESSE2 "-O3 ${CMAKE_CXX_FLAGS_RELEASESSE2}") set(CMAKE_C_FLAGS_RELEASESSE2 "-O3 ${CMAKE_C_FLAGS_RELEASESSE2}") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_C_FLAGS_RELWITHDEBINFO}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_C_FLAGS_RELWITHDEBINFO}") endif (LINUX) @@ -245,9 +293,9 @@ endif (DARWIN) if (LINUX OR DARWIN) set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs") - if (NOT GCC_DISABLE_FATAL_WARNINGS) + if (NOT DISABLE_FATAL_WARNINGS) set(GCC_WARNINGS "${GCC_WARNINGS} -Werror") - endif (NOT GCC_DISABLE_FATAL_WARNINGS) + endif (NOT DISABLE_FATAL_WARNINGS) set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor -Woverloaded-virtual") @@ -279,12 +327,12 @@ else (STANDALONE) endif (STANDALONE) if(1 EQUAL 1) - add_definitions(-DOPENSIM_RULES=1) - add_definitions(-DMESH_ENABLED=1) - add_definitions(-DENABLE_CLASSIC_CLOUDS=1) - if (NOT "$ENV{SHY_MOD}" STREQUAL "") - add_definitions(-DSHY_MOD=1) - endif (NOT "$ENV{SHY_MOD}" STREQUAL "") + add_definitions(-DOPENSIM_RULES=1) + add_definitions(-DMESH_ENABLED=1) + add_definitions(-DENABLE_CLASSIC_CLOUDS=1) + if (NOT "$ENV{SHY_MOD}" STREQUAL "") + add_definitions(-DSHY_MOD=1) + endif (NOT "$ENV{SHY_MOD}" STREQUAL "") endif(1 EQUAL 1) SET( CMAKE_EXE_LINKER_FLAGS_RELEASESSE2 diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index 3af703d26..5063cbe7a 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -168,19 +168,13 @@ long vfs_tell (void *datasource) return file->tell(); } -LLVorbisDecodeState::LLVorbisDecodeState(const LLUUID &uuid, const std::string &out_filename) -{ - mDone = FALSE; - mValid = FALSE; - mBytesRead = -1; - mUUID = uuid; - mInFilep = NULL; - mCurrentSection = 0; +LLVorbisDecodeState::LLVorbisDecodeState(const LLUUID &uuid, const std::string &out_filename) : + mValid(FALSE), mDone(FALSE), mBytesRead(-1), mUUID(uuid), #if !defined(USE_WAV_VFILE) - mOutFilename = out_filename; - mFileHandle = LLLFSThread::nullHandle(); + mOutFilename(out_filename), mFileHandle(LLLFSThread::nullHandle()), #endif - // No default value for mVF, it's an ogg structure? + mInFilep(NULL), mCurrentSection(0) +{ } LLVorbisDecodeState::~LLVorbisDecodeState() diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 2ff8856ec..29feeebc4 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -121,6 +121,7 @@ set(llcommon_HEADER_FILES llaprpool.h llassettype.h llassoclist.h + llatomic.h llavatarconstants.h llbase32.h llbase64.h diff --git a/indra/llcommon/aithreadsafe.h b/indra/llcommon/aithreadsafe.h index 0cff3b77a..a8b1ac490 100644 --- a/indra/llcommon/aithreadsafe.h +++ b/indra/llcommon/aithreadsafe.h @@ -26,8 +26,65 @@ * * 31/03/2010 * Initial version, written by Aleric Inglewood @ SL + * + * 14/03/2012 + * Added AIThreadSafeSingleThread and friends. + * Added AIAccessConst (and derived AIAccess from it) to allow read + * access to a const AIThreadSafeSimple. */ +// This file defines wrapper template classes for arbitrary types T +// adding locking to the instance and shielding it from access +// without first being locked. +// +// Locking and getting access works by creating a temporary (local) +// access object that takes the wrapper class as argument. Creating +// the access object obtains the lock, while destructing it releases +// the lock. +// +// There are three types of wrapper classes: +// AIThreadSafe, AIThreadSafeSimple and AIThreadSafeSingleThread. +// +// AIThreadSafe is for use with the access classes: +// AIReadAccessConst, AIReadAccess and AIWriteAccess. +// +// AIThreadSafeSimple is for use with the access classes: +// AIAccessConst and AIAccess. +// +// AIThreadSafeSingleThread is for use with the access classes: +// AISTAccessConst and AISTAccess. +// +// AIReadAccessConst provides read access to a const AIThreadSafe. +// AIReadAccess provides read access to a non-const AIThreadSafe. +// AIWriteAccess provides read/write access to a non-const AIThreadSafe. +// +// AIAccessConst provides read access to a const AIThreadSafeSimple. +// AIAccess provides read/write access to a non-const AIThreadSafeSimple. +// +// AISTAccessConst provides read access to a const AIThreadSafeSingleThread. +// AISTAccess provides read/write access to a non-const AIThreadSafeSingleThread. +// +// Thus, AIThreadSafe is to protect objects with a read/write lock, +// AIThreadSafeSimple is to protect objects with a single mutex, +// and AIThreadSafeSingleThread doesn't do any locking but makes sure +// (in Debug mode) that the wrapped object is only accessed by one thread. +// +// Each wrapper class allows it's wrapped object to be constructed +// with arbitrary parameters by using operator new with placement; +// for example, to instantiate a class Foo with read/write locking: +// +// AIThreadSafe foo(new (foo.memory()) Foo(param1, param2, ...)); +// +// Each wrapper class has a derived class that end on 'DC' (which +// stand for Default Constructed): AIThreadSafeDC, AIThreadSafeSimpleDC +// and AIThreadSafeSingleThreadDC. The default constructors of those +// wrapper classes cause the wrapped instance to be default constructed +// as well. They also provide a general one-parameter constructor. +// For example: +// +// AIThreadSafeDC foo; // Default constructed Foo. +// AIThreadSafeDC foo(3.4); // Foo with one constructor parameter. +// #ifndef AITHREADSAFE_H #define AITHREADSAFE_H @@ -49,15 +106,10 @@ template struct AIReadAccessConst; template struct AIReadAccess; template struct AIWriteAccess; +template struct AIAccessConst; template struct AIAccess; - -#if LL_WINDOWS -template class AIThreadSafeBits; -template -struct AIThreadSafeWindowsHack { - AIThreadSafeWindowsHack(AIThreadSafeBits& var, T* object); -}; -#endif +template struct AISTAccessConst; +template struct AISTAccess; template class AIThreadSafeBits @@ -80,10 +132,15 @@ public: // Only for use by AITHREADSAFE, see below. void* memory() const { return const_cast(&mMemory[0]); } + // Cast a T* back to AIThreadSafeBits. This is the inverse of memory(). + template + static AIThreadSafeBits* wrapper_cast(T2* ptr) + { return reinterpret_cast*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBits, mMemory[0])); } + template + static AIThreadSafeBits const* wrapper_cast(T2 const* ptr) + { return reinterpret_cast const*>(reinterpret_cast(ptr) - offsetof(AIThreadSafeBits, mMemory[0])); } + protected: -#if LL_WINDOWS - template friend struct AIThreadSafeWindowsHack; -#endif // Accessors. T const* ptr() const { return reinterpret_cast(mMemory); } T* ptr() { return reinterpret_cast(mMemory); } @@ -185,6 +242,14 @@ public: llassert(object == AIThreadSafeBits::ptr()); #endif } + +#if LL_DEBUG + // Can only be locked when there still exists an AIAccess object that + // references this object and will access it upon destruction. + // If the assertion fails, make sure that such AIAccess object is + // destructed before the deletion of this object. + ~AIThreadSafe() { llassert(!mRWLock.isLocked()); } +#endif }; /** @@ -194,48 +259,39 @@ public: * * * Foo foo(x, y); - * static Bar bar; + * static Bar bar(0.1, true); * * * One can instantiate a thread-safe instance with * * * AITHREADSAFE(Foo, foo, (x, y)); - * static AITHREADSAFE(Bar, bar, ); + * static AITHREADSAFE(Bar, bar, (0.1, true)); * * * Note: This macro does not allow to allocate such object on the heap. * If that is needed, have a look at AIThreadSafeDC. */ -#if LL_WINDOWS -template -AIThreadSafeWindowsHack::AIThreadSafeWindowsHack(AIThreadSafeBits& var, T* object) -{ - llassert(object == var.ptr()); -} -#define AITHREADSAFE(type, var, paramlist) \ - AIThreadSafe var(NULL); \ - AIThreadSafeWindowsHack dummy_##var(var, new (var.memory()) type paramlist) -#else #define AITHREADSAFE(type, var, paramlist) AIThreadSafe var(new (var.memory()) type paramlist) -#endif /** * @brief A wrapper class for objects that need to be accessed by more than one thread. * * This class is the same as an AIThreadSafe wrapper, except that it can only - * be used for default constructed objects. + * be used for default constructed objects, or constructed with one parameter. * * For example, instead of * * * Foo foo; + * Bar bar(3); * * * One would use * * * AIThreadSafeDC foo; + * AIThreadSafeDC bar(3); * * * The advantage over AITHREADSAFE is that this object can be allocated with @@ -253,6 +309,8 @@ class AIThreadSafeDC : public AIThreadSafe public: // Construct a wrapper around a default constructed object. AIThreadSafeDC(void) { new (AIThreadSafe::ptr()) T; } + // Allow an arbitrary parameter to be passed for construction. + template AIThreadSafeDC(T2 const& val) { new (AIThreadSafe::ptr()) T(val); } }; /** @@ -390,6 +448,7 @@ struct AIWriteAccess : public AIReadAccess * * AIAccess foo_w(foo); * // Use foo_w-> for read and write access. + * * * See also AIThreadSafe */ @@ -398,6 +457,7 @@ class AIThreadSafeSimple : public AIThreadSafeBits { protected: // Only this one may access the object (through ptr()). + friend struct AIAccessConst; friend struct AIAccess; // Locking control. @@ -411,6 +471,14 @@ protected: public: // Only for use by AITHREADSAFESIMPLE, see below. AIThreadSafeSimple(T* object) { llassert(object == AIThreadSafeBits::ptr()); } + +#if LL_DEBUG + // Can only be locked when there still exists an AIAccess object that + // references this object and will access it upon destruction. + // If the assertion fails, make sure that such AIAccess object is + // destructed before the deletion of this object. + ~AIThreadSafeSimple() { llassert(!mMutex.isLocked()); } +#endif }; /** @@ -420,14 +488,14 @@ public: * * * Foo foo(x, y); - * static Bar bar; + * static Bar bar(0.1, true); * * * One can instantiate a thread-safe instance with * * * AITHREADSAFESIMPLE(Foo, foo, (x, y)); - * static AITHREADSAFESIMPLE(Bar, bar, ); + * static AITHREADSAFESIMPLE(Bar, bar, (0.1, true)); * * * Note: This macro does not allow to allocate such object on the heap. @@ -439,18 +507,20 @@ public: * @brief A wrapper class for objects that need to be accessed by more than one thread. * * This class is the same as an AIThreadSafeSimple wrapper, except that it can only - * be used for default constructed objects. + * be used for default constructed objects, or constructed with one parameter. * * For example, instead of * * * Foo foo; + * Bar bar(0.1); * * * One would use * * * AIThreadSafeSimpleDC foo; + * AIThreadSafeSimpleDC bar(0.1); * * * The advantage over AITHREADSAFESIMPLE is that this object can be allocated with @@ -468,10 +538,12 @@ class AIThreadSafeSimpleDC : public AIThreadSafeSimple public: // Construct a wrapper around a default constructed object. AIThreadSafeSimpleDC(void) { new (AIThreadSafeSimple::ptr()) T; } + // Allow an arbitrary parameter to be passed for construction. + template AIThreadSafeSimpleDC(T2 const& val) { new (AIThreadSafeSimple::ptr()) T(val); } protected: // For use by AIThreadSafeSimpleDCRootPool - AIThreadSafeSimpleDC(LLAPRPool& parent) : AIThreadSafeSimple(parent) { new (AIThreadSafeSimple::ptr()) T; } + AIThreadSafeSimpleDC(LLAPRRootPool& parent) : AIThreadSafeSimple(parent) { new (AIThreadSafeSimple::ptr()) T; } }; // Helper class for AIThreadSafeSimpleDCRootPool to assure initialization of @@ -509,13 +581,13 @@ public: }; /** - * @brief Write lock object and provide read/write access. + * @brief Write lock object and provide read access. */ template -struct AIAccess +struct AIAccessConst { - //! Construct a AIAccess from a non-constant AIThreadSafeSimple. - AIAccess(AIThreadSafeSimple& wrapper) : mWrapper(wrapper) + //! Construct a AIAccessConst from a constant AIThreadSafeSimple. + AIAccessConst(AIThreadSafeSimple const& wrapper) : mWrapper(const_cast&>(wrapper)) #if AI_NEED_ACCESS_CC , mIsCopyConstructed(false) #endif @@ -524,12 +596,12 @@ struct AIAccess } //! Access the underlaying object for (read and) write access. - T* operator->() const { return this->mWrapper.ptr(); } + T const* operator->() const { return this->mWrapper.ptr(); } //! Access the underlaying object for (read and) write access. - T& operator*() const { return *this->mWrapper.ptr(); } + T const& operator*() const { return *this->mWrapper.ptr(); } - ~AIAccess() + ~AIAccessConst() { #if AI_NEED_ACCESS_CC if (mIsCopyConstructed) return; @@ -538,17 +610,229 @@ struct AIAccess } protected: - AIThreadSafeSimple& mWrapper; //!< Reference to the object that we provide access to. + AIThreadSafeSimple& mWrapper; //!< Reference to the object that we provide access to. #if AI_NEED_ACCESS_CC bool mIsCopyConstructed; public: - AIAccess(AIAccess const& orig) : mWrapper(orig.mWrapper), mIsCopyConstructed(true) { } + AIAccessConst(AIAccessConst const& orig) : mWrapper(orig.mWrapper), mIsCopyConstructed(true) { } #else private: // Disallow copy constructing directly. - AIAccess(AIAccess const&); + AIAccessConst(AIAccessConst const&); #endif }; +/** + * @brief Write lock object and provide read/write access. + */ +template +struct AIAccess : public AIAccessConst +{ + //! Construct a AIAccess from a non-constant AIThreadSafeSimple. + AIAccess(AIThreadSafeSimple& wrapper) : AIAccessConst(wrapper) { } + + //! Access the underlaying object for (read and) write access. + T* operator->() const { return this->mWrapper.ptr(); } + + //! Access the underlaying object for (read and) write access. + T& operator*() const { return *this->mWrapper.ptr(); } +}; + +/** + * @brief A wrapper class for objects that should only be accessed by a single thread. + * + * Use AITHREADSAFESINGLETHREAD to define instances of any type, and use AISTAccess + * to get access to the instance. + * + * For example, + * + * + * class Foo { public: Foo(int, int); }; + * + * AITHREADSAFESINGLETHREAD(Foo, foo, (2, 3)); + * + * AISTAccess foo_w(foo); + * // Use foo_w-> for read and write access. + * + */ +template +class AIThreadSafeSingleThread : public AIThreadSafeBits +{ +protected: + // Only these one may access the object (through ptr()). + friend struct AISTAccessConst; + friend struct AISTAccess; + + // For use by AIThreadSafeSingleThreadDC. + AIThreadSafeSingleThread(void) +#ifdef LL_DEBUG + : mAccessed(false) +#endif + { } + +#ifdef LL_DEBUG + mutable bool mAccessed; + mutable apr_os_thread_t mTheadID; + + void accessed(void) const + { + if (!mAccessed) + { + mAccessed = true; + mTheadID = apr_os_thread_current(); + } + else + { + llassert_always(apr_os_thread_equal(mTheadID, apr_os_thread_current())); + } + } +#endif + +public: + // Only for use by AITHREADSAFESINGLETHREAD, see below. + AIThreadSafeSingleThread(T* object) +#ifdef LL_DEBUG + : mAccessed(false) +#endif + { + llassert(object == AIThreadSafeBits::ptr()); + } + +private: + // Disallow copying or assignments. + AIThreadSafeSingleThread(AIThreadSafeSingleThread const&); + void operator=(AIThreadSafeSingleThread const&); +}; + +/** + * @brief A wrapper class for objects that should only be accessed by a single thread. + * + * This class is the same as an AIThreadSafeSingleThread wrapper, except that it can only + * be used for default constructed objects, or constructed with one parameter. + * + * For example, instead of + * + * + * Foo foo; + * Bar bar(0.1); + * + * + * One would use + * + * + * AIThreadSafeSingleThreadDC foo; + * AIThreadSafeSingleThreadDC bar(0.1); + * + * + * The advantage over AITHREADSAFESINGLETHREAD is that this object can be allocated with + * new on the heap. For example: + * + * + * AIThreadSafeSingleThreadDC* ptr = new AIThreadSafeSingleThreadDC; + * + * + * which is not possible with AITHREADSAFESINGLETHREAD. + * + * This class is primarily intended to test if some (member) variable needs locking, + * during development (in debug mode), and is therefore more flexible in that it + * automatically converts to the underlaying type, can be assigned to and can be + * written to an ostream, as if it wasn't wrapped at all. This is to reduce the + * impact on the source code. + */ +template +class AIThreadSafeSingleThreadDC : public AIThreadSafeSingleThread +{ +public: + // Construct a wrapper around a default constructed object. + AIThreadSafeSingleThreadDC(void) { new (AIThreadSafeSingleThread::ptr()) T; } + // Allow an arbitrary parameter to be passed for construction. + template AIThreadSafeSingleThreadDC(T2 const& val) { new (AIThreadSafeSingleThread::ptr()) T(val); } + + // Allow assigning with T. + AIThreadSafeSingleThreadDC& operator=(T const& val) { AIThreadSafeSingleThread::accessed(); *AIThreadSafeSingleThread::ptr() = val; return *this; } + // Allow writing to an ostream. + friend std::ostream& operator<<(std::ostream& os, AIThreadSafeSingleThreadDC const& wrapped_val) { wrapped_val.accessed(); return os << *wrapped_val.ptr(); } + + // Automatic conversion to T. + operator T&(void) { AIThreadSafeSingleThread::accessed(); return *AIThreadSafeSingleThread::ptr(); } + operator T const&(void) const { AIThreadSafeSingleThread::accessed(); return *AIThreadSafeSingleThread::ptr(); } +}; + +/** + * @brief Instantiate a static, global or local object of a given type wrapped in AIThreadSafeSingleThread, using an arbitrary constructor. + * + * For example, instead of doing + * + * + * Foo foo(x, y); + * static Bar bar; + * + * + * One can instantiate a thread-safe instance with + * + * + * AITHREADSAFESINGLETHREAD(Foo, foo, (x, y)); + * static AITHREADSAFESINGLETHREAD(Bar, bar, ); + * + * + * Note: This macro does not allow to allocate such object on the heap. + * If that is needed, have a look at AIThreadSafeSingleThreadDC. + */ +#define AITHREADSAFESINGLETHREAD(type, var, paramlist) AIThreadSafeSingleThread var(new (var.memory()) type paramlist) + +/** + * @brief Access single threaded object for read access. + */ +template +struct AISTAccessConst +{ + //! Construct a AISTAccessConst from a constant AIThreadSafeSingleThread. + AISTAccessConst(AIThreadSafeSingleThread const& wrapper) : mWrapper(const_cast&>(wrapper)) + { +#if LL_DEBUG + wrapper.accessed(); +#endif + } + + //! Access the underlaying object for read access. + T const* operator->() const { return this->mWrapper.ptr(); } + + //! Access the underlaying object for read write access. + T const& operator*() const { return *this->mWrapper.ptr(); } + +protected: + AIThreadSafeSingleThread& mWrapper; //!< Reference to the object that we provide access to. + +#if AI_NEED_ACCESS_CC +public: + AISTAccessConst(AISTAccessConst const& orig) : mWrapper(orig.mWrapper) { } +#else +private: + // Disallow copy constructing directly. + AISTAccessConst(AISTAccessConst const&); +#endif +}; + +/** + * @brief Access single threaded object for read/write access. + */ +template +struct AISTAccess : public AISTAccessConst +{ + //! Construct a AISTAccess from a non-constant AIThreadSafeSingleThread. + AISTAccess(AIThreadSafeSingleThread& wrapper) : AISTAccessConst(wrapper) + { +#if LL_DEBUG + wrapper.accessed(); +#endif + } + + //! Access the underlaying object for (read and) write access. + T* operator->() const { return this->mWrapper.ptr(); } + + //! Access the underlaying object for (read and) write access. + T& operator*() const { return *this->mWrapper.ptr(); } +}; + #endif diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index ee7717f12..d16b87cd7 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -88,7 +88,7 @@ bool ll_apr_warn_status(apr_status_t status) void ll_apr_assert_status(apr_status_t status) { - llassert(ll_apr_warn_status(status) == false); + llassert(!ll_apr_warn_status(status)); } //--------------------------------------------------------------------- @@ -146,7 +146,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc apr_status_t status; { - apr_pool_t* apr_file_open_pool; + apr_pool_t* apr_file_open_pool; // The use of apr_pool_t is OK here. // This is a temporary variable for a pool that is passed directly to apr_file_open below. if (access_type == short_lived) { @@ -199,7 +199,6 @@ apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOO // File I/O S32 LLAPRFile::read(void *buf, S32 nbytes) { - //llassert_always(mFile); (ASC-TUDCC) -HgB if(!mFile) { llwarns << "apr mFile is removed by somebody else. Can not read." << llendl ; @@ -222,7 +221,6 @@ S32 LLAPRFile::read(void *buf, S32 nbytes) S32 LLAPRFile::write(const void *buf, S32 nbytes) { - // llassert_always(mFile); (ASC-TUDCC) -HgB if(!mFile) { llwarns << "apr mFile is removed by somebody else. Can not write." << llendl ; diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index e7c3c53f1..61f3f97c0 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -91,29 +91,8 @@ protected: apr_thread_mutex_t* mMutex; }; -template class LLAtomic32 -{ -public: - LLAtomic32() {}; - LLAtomic32(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); }; - ~LLAtomic32() {}; - - operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); } - Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); } - void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); } - void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); } - Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++ - Type operator --(int) { return apr_atomic_dec32(&mData); } // Type-- - -private: - apr_uint32_t mData; -}; - -typedef LLAtomic32 LLAtomicU32; -typedef LLAtomic32 LLAtomicS32; - // File IO convenience functions. -// Returns NULL if the file fails to openm sets *sizep to file size of not NULL +// Returns NULL if the file fails to open, sets *sizep to file size if not NULL // abbreviated flags #define LL_APR_R (APR_READ) // "r" #define LL_APR_W (APR_CREATE|APR_TRUNCATE|APR_WRITE) // "w" @@ -131,7 +110,7 @@ typedef LLAtomic32 LLAtomicS32; // especially do not put some time-costly operations between open() and close(). // otherwise it might lock the APRFilePool. //there are two different apr_pools the APRFile can use: -// 1, a temperary pool passed to an APRFile function, which is used within this function and only once. +// 1, a temporary pool passed to an APRFile function, which is used within this function and only once. // 2, a global pool. // @@ -189,7 +168,7 @@ public: }; /** - * @brief Function which approprately logs error or remains quiet on + * @brief Function which appropriately logs error or remains quiet on * APR_SUCCESS. * @return Returns true if status is an error condition. */ diff --git a/indra/llcommon/llaprpool.cpp b/indra/llcommon/llaprpool.cpp index 03ab406a2..3559ff430 100644 --- a/indra/llcommon/llaprpool.cpp +++ b/indra/llcommon/llaprpool.cpp @@ -1,5 +1,5 @@ /** - * @file LLAPRPool.cpp + * @file llaprpool.cpp * * Copyright (c) 2010, Aleric Inglewood. * diff --git a/indra/llcommon/llaprpool.h b/indra/llcommon/llaprpool.h index aefdaa08b..dc123e942 100644 --- a/indra/llcommon/llaprpool.h +++ b/indra/llcommon/llaprpool.h @@ -1,5 +1,5 @@ /** - * @file LLAPRPool.h + * @file llaprpool.h * @brief Implementation of LLAPRPool. * * Copyright (c) 2010, Aleric Inglewood. @@ -60,9 +60,9 @@ extern void ll_init_apr(); class LL_COMMON_API LLAPRPool { protected: - apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized. + apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized. LLAPRPool* mParent; //!< Pointer to the parent pool, if any. Only valid when mPool is non-zero. - apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero. + apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero. public: //! Construct an uninitialized (destructed) pool. diff --git a/indra/llcommon/llatomic.h b/indra/llcommon/llatomic.h new file mode 100644 index 000000000..3cc5bcf38 --- /dev/null +++ b/indra/llcommon/llatomic.h @@ -0,0 +1,61 @@ +/** + * @file llatomic.h + * @brief Definition of LLAtomic + * + * $LicenseInfo:firstyear=2004&license=viewergpl$ + * + * Copyright (c) 2004-2009, Linden Research, Inc. + * Copyright (c) 2012, Aleric Inglewood + * + * 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_LLATOMIC_H +#define LL_LLATOMIC_H + +#include "apr_atomic.h" + +template class LLAtomic32 +{ +public: + LLAtomic32(void) { } + LLAtomic32(LLAtomic32 const& atom) { apr_uint32_t data = apr_atomic_read32(const_cast(&atom.mData)); apr_atomic_set32(&mData, data); } + LLAtomic32(Type x) { apr_atomic_set32(&mData, static_cast(x)); } + LLAtomic32& operator=(LLAtomic32 const& atom) { apr_uint32_t data = apr_atomic_read32(const_cast(&atom.mData)); apr_atomic_set32(&mData, data); return *this; } + + operator Type() const { apr_uint32_t data = apr_atomic_read32(const_cast(&mData)); return static_cast(data); } + void operator=(Type x) { apr_atomic_set32(&mData, static_cast(x)); } + void operator-=(Type x) { apr_atomic_sub32(&mData, static_cast(x)); } + void operator+=(Type x) { apr_atomic_add32(&mData, static_cast(x)); } + Type operator++(int) { return apr_atomic_inc32(&mData); } // Type++ + bool operator--() { return apr_atomic_dec32(&mData); } // Returns (--Type != 0) + +private: + apr_uint32_t mData; +}; + +typedef LLAtomic32 LLAtomicU32; +typedef LLAtomic32 LLAtomicS32; + +#endif diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 298dd4695..33b30ac72 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -39,7 +39,6 @@ void LLCommon::initClass() { LLMemory::initClass(); LLTimer::initClass(); - LLThreadSafeRefCount::initThreadSafeRefCount(); // LLWorkerThread::initClass(); // LLFrameCallbackManager::initClass(); } @@ -49,7 +48,6 @@ void LLCommon::cleanupClass() { // LLFrameCallbackManager::cleanupClass(); // LLWorkerThread::cleanupClass(); - LLThreadSafeRefCount::cleanupThreadSafeRefCount(); LLTimer::cleanupClass(); LLMemory::cleanupClass(); } diff --git a/indra/llcommon/llhash.h b/indra/llcommon/llhash.h index 0ce10883a..5451c11c1 100644 --- a/indra/llcommon/llhash.h +++ b/indra/llcommon/llhash.h @@ -39,6 +39,7 @@ #include #include #elif LL_DARWIN || LL_LINUX +#if CC_GCC # if GCC_VERSION >= 40300 // gcc 4.3 and up # include # elif GCC_VERSION >= 30400 // gcc 3.4 and up @@ -48,6 +49,9 @@ # else # include # endif +#elif CC_CLANG +# include +#endif #elif LL_SOLARIS #include #else diff --git a/indra/llcommon/lloptioninterface.h b/indra/llcommon/lloptioninterface.h index 4faf95f5e..dd5829d79 100644 --- a/indra/llcommon/lloptioninterface.h +++ b/indra/llcommon/lloptioninterface.h @@ -39,7 +39,7 @@ class LLSD; class LLOptionInterface { public: - virtual ~LLOptionInterface() = 0; + virtual ~LLOptionInterface(); virtual LLSD getOption(const std::string& name) const = 0; }; diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index ab73670ae..2680072bc 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -44,7 +44,7 @@ #include "llsimplehash.h" //============================================================================ -// Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small +// Note: ~LLQueuedThread is O(N) N=# of queued requests, assumed to be small // It is assumed that LLQueuedThreads are rarely created/destroyed. class LL_COMMON_API LLQueuedThread : public LLThread diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 803db8c3d..3716e5dab 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -68,6 +68,7 @@ U32 ll_thread_local local_thread_ID = 0; U32 LLThread::sIDIter = 0; LLAtomicS32 LLThread::sCount = 0; +LLAtomicS32 LLThread::sRunning = 0; LL_COMMON_API void assert_main_thread() { @@ -104,6 +105,11 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap // the moment it happens... therefore make a copy here. char const* volatile name = threadp->mName.c_str(); + // Always make sure that sRunning <= number of threads with status RUNNING, + // so do this before changing mStatus (meaning that once we see that we + // are STOPPED, then sRunning is also up to date). + --sRunning; + // We're done with the run function, this thread is done executing now. threadp->mStatus = STOPPED; @@ -114,6 +120,7 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap // the critical area of the mSignal lock)]. lldebugs << "LLThread::staticRun() Exiting: " << name << llendl; + --sRunning; // Would be better to do this after joining with the thread, but we don't join :/ return NULL; } @@ -178,7 +185,7 @@ void LLThread::shutdown() } mAPRThreadp = NULL; } - sCount--; + --sCount; delete mRunCondition; mRunCondition = 0; } @@ -189,6 +196,7 @@ void LLThread::start() // Set thread state to running mStatus = RUNNING; + sRunning++; apr_status_t status = apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool()); @@ -200,6 +208,7 @@ void LLThread::start() } else { + --sRunning; mStatus = STOPPED; llwarns << "failed to start thread " << mName << llendl; ll_apr_warn_status(status); @@ -402,6 +411,15 @@ LLMutexBase::LLMutexBase() : { } +bool LLMutexBase::isSelfLocked() const +{ +#if LL_DARWIN + return mLockingThread == LLThread::currentID(); +#else + return mLockingThread == local_thread_ID; +#endif +} + void LLMutexBase::lock() { #if LL_DARWIN @@ -435,37 +453,6 @@ void LLMutexBase::unlock() apr_thread_mutex_unlock(mAPRMutexp); } -bool LLMutexBase::isSelfLocked() -{ -#if LL_DARWIN - return mLockingThread == LLThread::currentID(); -#else - return mLockingThread == local_thread_ID; -#endif -} - -//---------------------------------------------------------------------------- - -//static -LLMutex* LLThreadSafeRefCount::sMutex = 0; - -//static -void LLThreadSafeRefCount::initThreadSafeRefCount() -{ - if (!sMutex) - { - sMutex = new LLMutex; - } -} - -//static -void LLThreadSafeRefCount::cleanupThreadSafeRefCount() -{ - delete sMutex; - sMutex = NULL; -} - - //---------------------------------------------------------------------------- LLThreadSafeRefCount::LLThreadSafeRefCount() : diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 2509ecf84..8def2c7ea 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -38,9 +38,13 @@ #include "llmemory.h" #include "apr_thread_cond.h" #include "llaprpool.h" +#include "llatomic.h" #ifdef SHOW_ASSERT extern LL_COMMON_API bool is_main_thread(void); +#define ASSERT_SINGLE_THREAD do { static apr_os_thread_t first_thread_id = apr_os_thread_current(); llassert(apr_os_thread_equal(first_thread_id, apr_os_thread_current())); } while(0) +#else +#define ASSERT_SINGLE_THREAD do { } while(0) #endif class LLThread; @@ -74,7 +78,8 @@ class LL_COMMON_API LLThread private: static U32 sIDIter; static LLAtomicS32 sCount; - + static LLAtomicS32 sRunning; + public: typedef enum e_thread_status { @@ -92,8 +97,9 @@ public: static U32 currentID(); // Return ID of current thread static S32 getCount() { return sCount; } + static S32 getRunning() { return sRunning; } static void yield(); // Static because it can be called by the main thread, which doesn't have an LLThread data structure. - + public: // PAUSE / RESUME functionality. See source code for important usage notes. // Called from MAIN THREAD. @@ -181,15 +187,18 @@ public: LLMutexBase() ; - void lock(); //blocks + void lock(); // blocks void unlock(); // Returns true if lock was obtained successfully. bool tryLock() { return !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); } // non-blocking, but does do a lock/unlock so not free bool isLocked() { bool is_not_locked = tryLock(); if (is_not_locked) unlock(); return !is_not_locked; } + + // Returns true if locked by this thread. + bool isSelfLocked() const; + // get ID of locking thread - bool isSelfLocked(); //return true if locked in a same thread U32 lockingThread() const { return mLockingThread; } protected: @@ -373,6 +382,16 @@ public: mNoHoldersCondition.signal(); // Tell waiting readers, see [5]. mNoHoldersCondition.unlock(); // Release lock on mHoldersCount. } +#if LL_DEBUG + // Really only intended for debugging purposes: + bool isLocked(void) + { + mNoHoldersCondition.lock(); + bool res = mHoldersCount; + mNoHoldersCondition.unlock(); + return res; + } +#endif }; //============================================================================ @@ -394,13 +413,6 @@ void LLThread::unlockData() class LL_COMMON_API LLThreadSafeRefCount { -public: - static void initThreadSafeRefCount(); // creates sMutex - static void cleanupThreadSafeRefCount(); // destroys sMutex - -private: - static LLMutex* sMutex; - private: LLThreadSafeRefCount(const LLThreadSafeRefCount&); // not implemented LLThreadSafeRefCount&operator=(const LLThreadSafeRefCount&); // not implemented @@ -413,31 +425,20 @@ public: void ref() { - if (sMutex) sMutex->lock(); mRef++; - if (sMutex) sMutex->unlock(); } - S32 unref() + void unref() { - llassert(mRef >= 1); - if (sMutex) sMutex->lock(); - S32 res = --mRef; - if (sMutex) sMutex->unlock(); - if (0 == res) - { - delete this; - return 0; - } - return res; - } + if (!--mRef) delete this; + } S32 getNumRefs() const { return mRef; } private: - S32 mRef; + LLAtomicS32 mRef; }; //============================================================================ diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index d6c2074f2..c3f4878ee 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -269,7 +269,7 @@ U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 si // LLImageRaw //--------------------------------------------------------------------------- -AITHREADSAFESIMPLE(S32, LLImageRaw::sGlobalRawMemory, ); +AIThreadSafeSimpleDC LLImageRaw::sGlobalRawMemory; S32 LLImageRaw::sRawImageCount = 0; S32 LLImageRaw::sRawImageCachedCount = 0; diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index b58dd5931..3eaf74b04 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -248,7 +248,7 @@ protected: void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; public: - static AIThreadSafeSimple sGlobalRawMemory; + static AIThreadSafeSimpleDC sGlobalRawMemory; static S32 sRawImageCount; static S32 sRawImageCachedCount; diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index e4e1d239e..e92ae5dc0 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -200,8 +200,6 @@ void LLParcel::init(const LLUUID &owner_id, mMediaWidth = 0; mMediaHeight = 0; setMediaCurrentURL(LLStringUtil::null); - mMediaURLFilterEnable = FALSE; - mMediaURLFilterList = LLSD::emptyArray(); mMediaAllowNavigate = TRUE; mMediaURLTimeout = 0.0f; mMediaPreventCameraZoom = FALSE; @@ -343,38 +341,6 @@ void LLParcel::setMediaURLResetTimer(F32 time) mMediaResetTimer.setTimerExpirySec(time); } -void LLParcel::setMediaURLFilterList(LLSD list) -{ - // sanity check LLSD - // must be array of strings - if (!list.isArray()) - { - return; - } - - for (S32 i = 0; i < list.size(); i++) - { - if (!list[i].isString()) - return; - } - - // can't be too big - const S32 MAX_SIZE = 50; - if (list.size() > MAX_SIZE) - { - LLSD new_list = LLSD::emptyArray(); - - for (S32 i = 0; i < llmin(list.size(), MAX_SIZE); i++) - { - new_list.append(list[i]); - } - - list = new_list; - } - - mMediaURLFilterList = list; -} - // virtual void LLParcel::setLocalID(S32 local_id) { @@ -629,34 +595,6 @@ BOOL LLParcel::importAccessEntry(std::istream& input_stream, LLAccessEntry* entr return input_stream.good(); } -BOOL LLParcel::importMediaURLFilter(std::istream& input_stream, std::string& url) -{ - skip_to_end_of_next_keyword("{", input_stream); - - while(input_stream.good()) - { - skip_comments_and_emptyspace(input_stream); - std::string line, keyword, value; - get_line(line, input_stream, MAX_STRING); - get_keyword_and_value(keyword, value, line); - - if ("}" == keyword) - { - break; - } - else if ("url" == keyword) - { - url = value; - } - else - { - llwarns << "Unknown keyword in parcel media url filter section: <" - << keyword << ">" << llendl; - } - } - return input_stream.good(); -} - // Assumes we are in a block "ParcelData" void LLParcel::packMessage(LLMessageSystem* msg) { @@ -703,8 +641,6 @@ void LLParcel::packMessage(LLSD& msg) msg["media_allow_navigate"] = getMediaAllowNavigate(); msg["media_prevent_camera_zoom"] = getMediaPreventCameraZoom(); msg["media_url_timeout"] = getMediaURLTimeout(); - msg["media_url_filter_enable"] = getMediaURLFilterEnable(); - msg["media_url_filter_list"] = getMediaURLFilterList(); msg["group_id"] = getGroupID(); msg["pass_price"] = mPassPrice; msg["pass_hours"] = mPassHours; @@ -795,7 +731,6 @@ void LLParcel::unpackMessage(LLMessageSystem* msg) msg->getString("MediaLinkSharing", "MediaCurrentURL", buffer); setMediaCurrentURL(buffer); msg->getU8 ( "MediaLinkSharing", "MediaAllowNavigate", mMediaAllowNavigate ); - msg->getU8 ( "MediaLinkSharing", "MediaURLFilterEnable", mMediaURLFilterEnable ); msg->getU8 ( "MediaLinkSharing", "MediaPreventCameraZoom", mMediaPreventCameraZoom ); msg->getF32( "MediaLinkSharing", "MediaURLTimeout", mMediaURLTimeout); } @@ -1256,8 +1191,6 @@ void LLParcel::clearParcel() mMediaWidth = 0; mMediaHeight = 0; setMediaCurrentURL(LLStringUtil::null); - setMediaURLFilterList(LLSD::emptyArray()); - setMediaURLFilterEnable(FALSE); setMediaAllowNavigate(TRUE); setMediaPreventCameraZoom(FALSE); setMediaURLTimeout(0.0f); diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 3479e5982..492be170b 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -253,8 +253,6 @@ public: void setMediaWidth(S32 width); void setMediaHeight(S32 height); void setMediaCurrentURL(const std::string& url); - void setMediaURLFilterEnable(U8 enable) { mMediaURLFilterEnable = enable; } - void setMediaURLFilterList(LLSD list); void setMediaAllowNavigate(U8 enable) { mMediaAllowNavigate = enable; } void setMediaURLTimeout(F32 timeout) { mMediaURLTimeout = timeout; } void setMediaPreventCameraZoom(U8 enable) { mMediaPreventCameraZoom = enable; } @@ -317,7 +315,6 @@ public: // BOOL importStream(std::istream& input_stream); BOOL importAccessEntry(std::istream& input_stream, LLAccessEntry* entry); // BOOL exportStream(std::ostream& output_stream); - BOOL importMediaURLFilter(std::istream& input_stream, std::string& url); void packMessage(LLMessageSystem* msg); void packMessage(LLSD& msg); @@ -360,8 +357,6 @@ public: U8 getMediaAutoScale() const { return mMediaAutoScale; } U8 getMediaLoop() const { return mMediaLoop; } const std::string& getMediaCurrentURL() const { return mMediaCurrentURL; } - U8 getMediaURLFilterEnable() const { return mMediaURLFilterEnable; } - LLSD getMediaURLFilterList() const { return mMediaURLFilterList; } U8 getMediaAllowNavigate() const { return mMediaAllowNavigate; } F32 getMediaURLTimeout() const { return mMediaURLTimeout; } U8 getMediaPreventCameraZoom() const { return mMediaPreventCameraZoom; } @@ -657,8 +652,6 @@ protected: U8 mMediaLoop; std::string mMediaCurrentURL; LLUUID mMediaID; - U8 mMediaURLFilterEnable; - LLSD mMediaURLFilterList; U8 mMediaAllowNavigate; U8 mMediaPreventCameraZoom; F32 mMediaURLTimeout; diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index b13eddc4e..c8a0875f5 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -309,7 +309,7 @@ public: //is it here? if (isInside(data->getPositionGroup())) { - if ((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius()) || + if (((getElementCount() < gOctreeMaxCapacity && contains(data->getBinRadius())) || (data->getBinRadius() > getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) { //it belongs here #if LL_OCTREE_PARANOIA_CHECK diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index fc1da1b56..8b47a92ea 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2097,7 +2097,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge generate(); - if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE || mParams.getSculptType() == LL_SCULPT_TYPE_MESH) + if ((mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) || mParams.getSculptType() == LL_SCULPT_TYPE_MESH) { createVolumeFaces(); } diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt index a328d16e0..b09245ba3 100644 --- a/indra/llmessage/CMakeLists.txt +++ b/indra/llmessage/CMakeLists.txt @@ -34,7 +34,6 @@ set(llmessage_SOURCE_FILES lldispatcher.cpp llfiltersd2xmlrpc.cpp llhost.cpp - llhttpassetstorage.cpp llhttpclient.cpp llhttpclientadapter.cpp llhttpnode.cpp @@ -125,7 +124,6 @@ set(llmessage_HEADER_FILES llfiltersd2xmlrpc.h llfollowcamparams.h llhost.h - llhttpassetstorage.h llhttpclient.h llhttpclientinterface.h llhttpclientadapter.h diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp index e0410906f..4b41abd45 100644 --- a/indra/llmessage/llcircuit.cpp +++ b/indra/llmessage/llcircuit.cpp @@ -688,7 +688,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) // now, check to see if we've got a gap U32 gap = 0; - if ((mPacketsInID == id)) + if (mPacketsInID == id) { // nope! bump and wrap the counter, then return mPacketsInID++; diff --git a/indra/llmessage/llhttpassetstorage.cpp b/indra/llmessage/llhttpassetstorage.cpp deleted file mode 100644 index 612d76596..000000000 --- a/indra/llmessage/llhttpassetstorage.cpp +++ /dev/null @@ -1,1459 +0,0 @@ -/** - * @file llhttpassetstorage.cpp - * @brief Subclass capable of loading asset data to/from an external - * source. Currently, a web server accessed via curl - * - * $LicenseInfo:firstyear=2003&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "linden_common.h" - -#include "llhttpassetstorage.h" - -#include - -#include "indra_constants.h" -#include "message.h" -#include "llproxy.h" -#include "llvfile.h" -#include "llvfs.h" - -#ifdef LL_STANDALONE -# include -#else -# include "zlib/zlib.h" -#endif - -const U32 MAX_RUNNING_REQUESTS = 1; -const F32 MAX_PROCESSING_TIME = 0.005f; -const S32 CURL_XFER_BUFFER_SIZE = 65536; -// Try for 30 minutes for now. -const F32 GET_URL_TO_FILE_TIMEOUT = 1800.0f; - -const S32 COMPRESSED_INPUT_BUFFER_SIZE = 4096; - -const S32 HTTP_OK = 200; -const S32 HTTP_PUT_OK = 201; -const S32 HTTP_NO_CONTENT = 204; -const S32 HTTP_MISSING = 404; -const S32 HTTP_SERVER_BAD_GATEWAY = 502; -const S32 HTTP_SERVER_TEMP_UNAVAILABLE = 503; - -///////////////////////////////////////////////////////////////////////////////// -// LLTempAssetData -// An asset not stored on central asset store, but on a simulator node somewhere. -///////////////////////////////////////////////////////////////////////////////// -struct LLTempAssetData -{ - LLUUID mAssetID; - LLUUID mAgentID; - std::string mHostName; -}; - -///////////////////////////////////////////////////////////////////////////////// -// LLHTTPAssetRequest -///////////////////////////////////////////////////////////////////////////////// - -class LLHTTPAssetRequest : public LLAssetRequest -{ -public: - LLHTTPAssetRequest(LLHTTPAssetStorage *asp, const LLUUID &uuid, - LLAssetType::EType type, LLAssetStorage::ERequestType rt, - const std::string& url, CURLM *curl_multi); - virtual ~LLHTTPAssetRequest(); - - void setupCurlHandle(); - void cleanupCurlHandle(); - - void prepareCompressedUpload(); - void finishCompressedUpload(); - size_t readCompressedData(void* data, size_t size); - - static size_t curlCompressedUploadCallback( - void *data, size_t size, size_t nmemb, void *user_data); - - virtual LLSD getTerseDetails() const; - virtual LLSD getFullDetails() const; - -public: - LLHTTPAssetStorage *mAssetStoragep; - - CURL *mCurlHandle; - CURLM *mCurlMultiHandle; - std::string mURLBuffer; - struct curl_slist *mHTTPHeaders; - LLVFile *mVFile; - LLUUID mTmpUUID; - LLAssetStorage::ERequestType mRequestType; - - bool mZInitialized; - z_stream mZStream; - char* mZInputBuffer; - bool mZInputExhausted; - - FILE *mFP; -}; - - -LLHTTPAssetRequest::LLHTTPAssetRequest(LLHTTPAssetStorage *asp, - const LLUUID &uuid, - LLAssetType::EType type, - LLAssetStorage::ERequestType rt, - const std::string& url, - CURLM *curl_multi) - : LLAssetRequest(uuid, type), - mZInitialized(false) -{ - memset(&mZStream, 0, sizeof(mZStream)); // we'll initialize this later, but for now zero the whole C-style struct to avoid debug/coverity noise - mAssetStoragep = asp; - mCurlHandle = NULL; - mCurlMultiHandle = curl_multi; - mVFile = NULL; - mRequestType = rt; - mHTTPHeaders = NULL; - mFP = NULL; - mZInputBuffer = NULL; - mZInputExhausted = false; - - mURLBuffer = url; -} - -LLHTTPAssetRequest::~LLHTTPAssetRequest() -{ - // Cleanup/cancel the request - if (mCurlHandle) - { - curl_multi_remove_handle(mCurlMultiHandle, mCurlHandle); - cleanupCurlHandle(); - } - if (mHTTPHeaders) - { - curl_slist_free_all(mHTTPHeaders); - } - delete mVFile; - finishCompressedUpload(); -} - -// virtual -LLSD LLHTTPAssetRequest::getTerseDetails() const -{ - LLSD sd = LLAssetRequest::getTerseDetails(); - - sd["url"] = mURLBuffer; - - return sd; -} - -// virtual -LLSD LLHTTPAssetRequest::getFullDetails() const -{ - LLSD sd = LLAssetRequest::getFullDetails(); - - if (mCurlHandle) - { - long curl_response = -1; - long curl_connect = -1; - double curl_total_time = -1.0f; - double curl_size_upload = -1.0f; - double curl_size_download = -1.0f; - double curl_content_length_upload = -1.0f; - double curl_content_length_download = -1.0f; - long curl_request_size = -1; - const char* curl_content_type = NULL; - - curl_easy_getinfo(mCurlHandle, CURLINFO_HTTP_CODE, &curl_response); - curl_easy_getinfo(mCurlHandle, CURLINFO_HTTP_CONNECTCODE, &curl_connect); - curl_easy_getinfo(mCurlHandle, CURLINFO_TOTAL_TIME, &curl_total_time); - curl_easy_getinfo(mCurlHandle, CURLINFO_SIZE_UPLOAD, &curl_size_upload); - curl_easy_getinfo(mCurlHandle, CURLINFO_SIZE_DOWNLOAD, &curl_size_download); - curl_easy_getinfo(mCurlHandle, CURLINFO_CONTENT_LENGTH_UPLOAD, &curl_content_length_upload); - curl_easy_getinfo(mCurlHandle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &curl_content_length_download); - curl_easy_getinfo(mCurlHandle, CURLINFO_REQUEST_SIZE, &curl_request_size); - curl_easy_getinfo(mCurlHandle, CURLINFO_CONTENT_TYPE, &curl_content_type); - - sd["curl_response_code"] = (int) curl_response; - sd["curl_http_connect_code"] = (int) curl_connect; - sd["curl_total_time"] = curl_total_time; - sd["curl_size_upload"] = curl_size_upload; - sd["curl_size_download"] = curl_size_download; - sd["curl_content_length_upload"] = curl_content_length_upload; - sd["curl_content_length_download"] = curl_content_length_download; - sd["curl_request_size"] = (int) curl_request_size; - if (curl_content_type) - { - sd["curl_content_type"] = curl_content_type; - } - else - { - sd["curl_content_type"] = ""; - } - } - - sd["temp_id"] = mTmpUUID; - sd["request_type"] = LLAssetStorage::getRequestName(mRequestType); - sd["z_initialized"] = mZInitialized; - sd["z_input_exhausted"] = mZInputExhausted; - - S32 file_size = -1; - if (mFP) - { - struct stat file_stat; - int file_desc = fileno(mFP); - if ( fstat(file_desc, &file_stat) == 0) - { - file_size = file_stat.st_size; - } - } - sd["file_size"] = file_size; - - return sd; -} - - -void LLHTTPAssetRequest::setupCurlHandle() -{ - // *NOTE: Similar code exists in mapserver/llcurlutil.cpp JC - mCurlHandle = LLCurl::newEasyHandle(); - llassert_always(mCurlHandle != NULL) ; - - // Apply proxy settings if configured to do so - LLProxy::getInstance()->applyProxySettings(mCurlHandle); - - curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1); - curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1); - curl_easy_setopt(mCurlHandle, CURLOPT_URL, mURLBuffer.c_str()); - curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this); - if (LLAssetStorage::RT_DOWNLOAD == mRequestType) - { - curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); - // only do this on downloads, as uploads - // to some apache configs (like our test grids) - // mistakenly claim the response is gzip'd if the resource - // name ends in .gz, even though in a PUT, the response is - // just plain HTML saying "created" - } - /* Remove the Pragma: no-cache header that libcurl inserts by default; - we want the cached version, if possible. */ - if (mZInitialized) - { - curl_easy_setopt(mCurlHandle, CURLOPT_PROXY, ""); - // disable use of proxy, which can't handle chunked transfers - } - mHTTPHeaders = curl_slist_append(mHTTPHeaders, "Pragma:"); - - // bug in curl causes DNS to be cached for too long a time, 0 sets it to never cache DNS results internally (to curl) - curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); - - // resist the temptation to explicitly add the Transfer-Encoding: chunked - // header here - invokes a libCURL bug - curl_easy_setopt(mCurlHandle, CURLOPT_HTTPHEADER, mHTTPHeaders); - if (mAssetStoragep) - { - // Set the appropriate pending upload or download flag - mAssetStoragep->addRunningRequest(mRequestType, this); - } - else - { - llerrs << "LLHTTPAssetRequest::setupCurlHandle - No asset storage associated with this request!" << llendl; - } -} - -void LLHTTPAssetRequest::cleanupCurlHandle() -{ - LLCurl::deleteEasyHandle(mCurlHandle); - if (mAssetStoragep) - { - // Terminating a request. Thus upload or download is no longer pending. - mAssetStoragep->removeRunningRequest(mRequestType, this); - } - else - { - llerrs << "LLHTTPAssetRequest::~LLHTTPAssetRequest - No asset storage associated with this request!" << llendl; - } - mCurlHandle = NULL; -} - -void LLHTTPAssetRequest::prepareCompressedUpload() -{ - mZStream.next_in = Z_NULL; - mZStream.avail_in = 0; - mZStream.zalloc = Z_NULL; - mZStream.zfree = Z_NULL; - mZStream.opaque = Z_NULL; - - int r = deflateInit2(&mZStream, - 1, // compression level - Z_DEFLATED, // the only method defined - 15 + 16, // the default windowBits + gzip header flag - 8, // the default memLevel - Z_DEFAULT_STRATEGY); - - if (r != Z_OK) - { - llerrs << "LLHTTPAssetRequest::prepareCompressedUpload defalateInit2() failed" << llendl; - } - - mZInitialized = true; - mZInputBuffer = new char[COMPRESSED_INPUT_BUFFER_SIZE]; - mZInputExhausted = false; - - mVFile = new LLVFile(gAssetStorage->mVFS, - getUUID(), getType(), LLVFile::READ); -} - -void LLHTTPAssetRequest::finishCompressedUpload() -{ - if (mZInitialized) - { - llinfos << "LLHTTPAssetRequest::finishCompressedUpload: " - << "read " << mZStream.total_in << " byte asset file, " - << "uploaded " << mZStream.total_out << " byte compressed asset" - << llendl; - - deflateEnd(&mZStream); - delete[] mZInputBuffer; - } -} - -size_t LLHTTPAssetRequest::readCompressedData(void* data, size_t size) -{ - llassert(mZInitialized); - - mZStream.next_out = (Bytef*)data; - mZStream.avail_out = size; - - while (mZStream.avail_out > 0) - { - if (mZStream.avail_in == 0 && !mZInputExhausted) - { - S32 to_read = llmin(COMPRESSED_INPUT_BUFFER_SIZE, - (S32)(mVFile->getSize() - mVFile->tell())); - - if ( to_read > 0 ) - { - mVFile->read((U8*)mZInputBuffer, to_read); /*Flawfinder: ignore*/ - mZStream.next_in = (Bytef*)mZInputBuffer; - mZStream.avail_in = mVFile->getLastBytesRead(); - } - - mZInputExhausted = mZStream.avail_in == 0; - } - - int r = deflate(&mZStream, - mZInputExhausted ? Z_FINISH : Z_NO_FLUSH); - - if (r == Z_STREAM_END || r < 0 || mZInputExhausted) - { - if (r < 0) - { - llwarns << "LLHTTPAssetRequest::readCompressedData: deflate returned error code " - << (S32) r << llendl; - } - break; - } - } - - return size - mZStream.avail_out; -} - -//static -size_t LLHTTPAssetRequest::curlCompressedUploadCallback( - void *data, size_t size, size_t nmemb, void *user_data) -{ - size_t num_read = 0; - - if (gAssetStorage) - { - CURL *curl_handle = (CURL *)user_data; - LLHTTPAssetRequest *req = NULL; - curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req); - if (req) - { - num_read = req->readCompressedData(data, size * nmemb); - } - } - - return num_read; -} - -///////////////////////////////////////////////////////////////////////////////// -// LLHTTPAssetStorage -///////////////////////////////////////////////////////////////////////////////// - - -LLHTTPAssetStorage::LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, - LLVFS *vfs, LLVFS *static_vfs, - const LLHost &upstream_host, - const std::string& web_host, - const std::string& local_web_host, - const std::string& host_name) - : LLAssetStorage(msg, xfer, vfs, static_vfs, upstream_host) -{ - _init(web_host, local_web_host, host_name); -} - -LLHTTPAssetStorage::LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, - LLVFS *vfs, - LLVFS *static_vfs, - const std::string& web_host, - const std::string& local_web_host, - const std::string& host_name) - : LLAssetStorage(msg, xfer, vfs, static_vfs) -{ - _init(web_host, local_web_host, host_name); -} - -void LLHTTPAssetStorage::_init(const std::string& web_host, const std::string& local_web_host, const std::string& host_name) -{ - mBaseURL = web_host; - mLocalBaseURL = local_web_host; - mHostName = host_name; - - // curl_global_init moved to LLCurl::initClass() - - mCurlMultiHandle = LLCurl::newMultiHandle() ; - llassert_always(mCurlMultiHandle != NULL) ; -} - -LLHTTPAssetStorage::~LLHTTPAssetStorage() -{ - LLCurl::deleteMultiHandle(mCurlMultiHandle); - mCurlMultiHandle = NULL; - - // curl_global_cleanup moved to LLCurl::initClass() -} - -// storing data is simpler than getting it, so we just overload the whole method -void LLHTTPAssetStorage::storeAssetData( - const LLUUID& uuid, - LLAssetType::EType type, - LLAssetStorage::LLStoreAssetCallback callback, - void* user_data, - bool temp_file, - bool is_priority, - bool store_local, - const LLUUID& requesting_agent_id, - bool user_waiting, - F64 timeout) -{ - if (mVFS->getExists(uuid, type)) // VFS treats nonexistant and zero-length identically - { - LLAssetRequest *req = new LLAssetRequest(uuid, type); - req->mUpCallback = callback; - req->mUserData = user_data; - req->mRequestingAgentID = requesting_agent_id; - req->mIsUserWaiting = user_waiting; - req->mTimeout = timeout; - - // LLAssetStorage metric: Successful Request - S32 size = mVFS->getSize(uuid, type); - const char *message; - if( store_local ) - { - message = "Added to local upload queue"; - } - else - { - message = "Added to upload queue"; - } - reportMetric( uuid, type, LLStringUtil::null, requesting_agent_id, size, MR_OKAY, __FILE__, __LINE__, message ); - - // this will get picked up and transmitted in checkForTimeouts - if(store_local) - { - mPendingLocalUploads.push_back(req); - } - else if(is_priority) - { - mPendingUploads.push_front(req); - } - else - { - mPendingUploads.push_back(req); - } - } - else - { - llwarns << "AssetStorage: attempt to upload non-existent vfile " << uuid << ":" << LLAssetType::lookup(type) << llendl; - if (callback) - { - // LLAssetStorage metric: Zero size VFS - reportMetric( uuid, type, LLStringUtil::null, requesting_agent_id, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file didn't exist or was zero length (VFS - can't tell which)" ); - callback(uuid, user_data, LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE, LL_EXSTAT_NONEXISTENT_FILE); - } - } -} - -// virtual -void LLHTTPAssetStorage::storeAssetData( - const std::string& filename, - const LLUUID& asset_id, - LLAssetType::EType asset_type, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file, - bool is_priority, - bool user_waiting, - F64 timeout) -{ - llinfos << "LLAssetStorage::storeAssetData (legacy)" << asset_id << ":" << LLAssetType::lookup(asset_type) << llendl; - - LLLegacyAssetRequest *legacy = new LLLegacyAssetRequest; - - legacy->mUpCallback = callback; - legacy->mUserData = user_data; - - FILE *fp = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ - S32 size = 0; - if (fp) - { - fseek(fp, 0, SEEK_END); - size = ftell(fp); - fseek(fp, 0, SEEK_SET); - } - - if( size ) - { - LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE); - - file.setMaxSize(size); - - const S32 buf_size = 65536; - U8 copy_buf[buf_size]; - while ((size = (S32)fread(copy_buf, 1, buf_size, fp))) - { - file.write(copy_buf, size); - } - fclose(fp); - - // if this upload fails, the caller needs to setup a new tempfile for us - if (temp_file) - { - LLFile::remove(filename); - } - - // LLAssetStorage metric: Success not needed; handled in the overloaded method here: - storeAssetData( - asset_id, - asset_type, - legacyStoreDataCallback, - (void**)legacy, - temp_file, - is_priority, - false, - LLUUID::null, - user_waiting, - timeout); - } - else // !size - { - if( fp ) - { - // LLAssetStorage metric: Zero size - reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file was zero length" ); - fclose( fp ); - } - else - { - // LLAssetStorage metric: Missing File - reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_FILE_NONEXIST, __FILE__, __LINE__, "The file didn't exist" ); - } - if (callback) - { - callback(LLUUID::null, user_data, LL_ERR_CANNOT_OPEN_FILE, LL_EXSTAT_BLOCKED_FILE); - } - delete legacy; - } -} - -// virtual -LLSD LLHTTPAssetStorage::getPendingDetails(LLAssetStorage::ERequestType rt, - LLAssetType::EType asset_type, - const std::string& detail_prefix) const -{ - LLSD sd = LLAssetStorage::getPendingDetails(rt, asset_type, detail_prefix); - const request_list_t* running = getRunningList(rt); - if (running) - { - // Loop through the pending requests sd, and add extra info about its running status. - S32 num_pending = sd["requests"].size(); - S32 i; - for (i = 0; i < num_pending; ++i) - { - LLSD& pending = sd["requests"][i]; - // See if this pending request is running. - const LLAssetRequest* req = findRequest(running, - LLAssetType::lookup(pending["type"].asString()), - pending["asset_id"]); - if (req) - { - // Keep the detail_url so we don't have to rebuild it. - LLURI detail_url = pending["detail"]; - pending = req->getTerseDetails(); - pending["detail"] = detail_url; - pending["is_running"] = true; - } - else - { - pending["is_running"] = false; - } - } - } - return sd; -} - -// virtual -LLSD LLHTTPAssetStorage::getPendingRequest(LLAssetStorage::ERequestType rt, - LLAssetType::EType asset_type, - const LLUUID& asset_id) const -{ - // Look for this asset in the running list first. - const request_list_t* running = getRunningList(rt); - if (running) - { - LLSD sd = LLAssetStorage::getPendingRequestImpl(running, asset_type, asset_id); - if (sd) - { - sd["is_running"] = true; - return sd; - } - } - LLSD sd = LLAssetStorage::getPendingRequest(rt, asset_type, asset_id); - if (sd) - { - sd["is_running"] = false; - } - return sd; -} - -// virtual -bool LLHTTPAssetStorage::deletePendingRequest(LLAssetStorage::ERequestType rt, - LLAssetType::EType asset_type, - const LLUUID& asset_id) -{ - // Try removing this from the running list first. - request_list_t* running = getRunningList(rt); - if (running) - { - LLAssetRequest* req = findRequest(running, asset_type, asset_id); - if (req) - { - // Remove this request from the running list to get it out of curl. - running->remove(req); - - // Find this request in the pending list, so we can move it to the end of the line. - request_list_t* pending = getRequestList(rt); - if (pending) - { - request_list_t::iterator result = std::find_if(pending->begin(), pending->end(), - std::bind2nd(ll_asset_request_equal(), req)); - if (pending->end() != result) - { - // This request was found in the pending list. Move it to the end! - LLAssetRequest* pending_req = *result; - pending->remove(pending_req); - - if (!pending_req->mIsUserWaiting) //A user is waiting on this request. Toss it. - { - pending->push_back(pending_req); - } - else - { - if (pending_req->mUpCallback) //Clean up here rather than _callUploadCallbacks because this request is already cleared the req. - { - pending_req->mUpCallback(pending_req->getUUID(), pending_req->mUserData, -1, LL_EXSTAT_REQUEST_DROPPED); - } - - } - - llinfos << "Asset " << getRequestName(rt) << " request for " - << asset_id << "." << LLAssetType::lookup(asset_type) - << " removed from curl and placed at the end of the pending queue." - << llendl; - } - else - { - llwarns << "Unable to find pending " << getRequestName(rt) << " request for " - << asset_id << "." << LLAssetType::lookup(asset_type) << llendl; - } - } - delete req; - - return true; - } - } - return LLAssetStorage::deletePendingRequest(rt, asset_type, asset_id); -} - -// internal requester, used by getAssetData in superclass -void LLHTTPAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, - void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), - void *user_data, BOOL duplicate, - BOOL is_priority) -{ - // stash the callback info so we can find it after we get the response message - LLAssetRequest *req = new LLAssetRequest(uuid, type); - req->mDownCallback = callback; - req->mUserData = user_data; - req->mIsPriority = is_priority; - - // this will get picked up and downloaded in checkForTimeouts - - // - // HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK! Asset requests were taking too long and timing out. - // Since texture requests are the LEAST sensitive (on the simulator) to being delayed, add - // non-texture requests to the front, and add texture requests to the back. The theory is - // that we always want them first, even if they're out of order. - // - - if (req->getType() == LLAssetType::AT_TEXTURE) - { - mPendingDownloads.push_back(req); - } - else - { - mPendingDownloads.push_front(req); - } -} - -LLAssetRequest* LLHTTPAssetStorage::findNextRequest(LLAssetStorage::request_list_t& pending, - LLAssetStorage::request_list_t& running) -{ - // Early exit if the running list is full, or we don't have more pending than running. - if (running.size() >= MAX_RUNNING_REQUESTS - || pending.size() <= running.size()) return NULL; - - // Look for the first pending request that is not already running. - request_list_t::iterator running_begin = running.begin(); - request_list_t::iterator running_end = running.end(); - - request_list_t::iterator pending_iter = pending.begin(); - request_list_t::iterator pending_end = pending.end(); - // Loop over all pending requests until we miss finding it in the running list. - for (; pending_iter != pending.end(); ++pending_iter) - { - LLAssetRequest* req = *pending_iter; - // Look for this pending request in the running list. - if (running_end == std::find_if(running_begin, running_end, - std::bind2nd(ll_asset_request_equal(), req))) - { - // It isn't running! Return it. - return req; - } - } - return NULL; -} - -// overloaded to additionally move data to/from the webserver -void LLHTTPAssetStorage::checkForTimeouts() -{ - CURLMcode mcode; - LLAssetRequest *req; - while ( (req = findNextRequest(mPendingDownloads, mRunningDownloads)) ) - { - // Setup this curl download request - // We need to generate a new request here - // since the one in the list could go away - std::string tmp_url; - std::string uuid_str; - req->getUUID().toString(uuid_str); - std::string base_url = getBaseURL(req->getUUID(), req->getType()); - tmp_url = llformat("%s/%36s.%s", base_url.c_str() , uuid_str.c_str(), LLAssetType::lookup(req->getType())); - - LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), - req->getType(), RT_DOWNLOAD, tmp_url, mCurlMultiHandle); - new_req->mTmpUUID.generate(); - - // Sets pending download flag internally - new_req->setupCurlHandle(); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_FOLLOWLOCATION, TRUE); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &curlDownCallback); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEDATA, new_req->mCurlHandle); - - mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle); - if (mcode > CURLM_OK) - { - // Failure. Deleting the pending request will remove it from the running - // queue, and push it to the end of the pending queue. - new_req->cleanupCurlHandle(); - deletePendingRequest(RT_DOWNLOAD, new_req->getType(), new_req->getUUID()); - break; - } - else - { - llinfos << "Requesting " << new_req->mURLBuffer << llendl; - } - } - - while ( (req = findNextRequest(mPendingUploads, mRunningUploads)) ) - { - // setup this curl upload request - - bool do_compress = req->getType() == LLAssetType::AT_OBJECT; - - std::string tmp_url; - std::string uuid_str; - req->getUUID().toString(uuid_str); - tmp_url = mBaseURL + "/" + uuid_str + "." + LLAssetType::lookup(req->getType()); - if (do_compress) tmp_url += ".gz"; - - LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), - req->getType(), RT_UPLOAD, tmp_url, mCurlMultiHandle); - - if (req->mIsUserWaiting) //If a user is waiting on a realtime response, we want to perserve information across upload attempts. - { - new_req->mTime = req->mTime; - new_req->mTimeout = req->mTimeout; - new_req->mIsUserWaiting = req->mIsUserWaiting; - } - - if (do_compress) - { - new_req->prepareCompressedUpload(); - } - - // Sets pending upload flag internally - new_req->setupCurlHandle(); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_UPLOAD, 1); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &nullOutputCallback); - - if (do_compress) - { - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION, - &LLHTTPAssetRequest::curlCompressedUploadCallback); - } - else - { - LLVFile file(mVFS, req->getUUID(), req->getType()); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_INFILESIZE, file.getSize()); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION, - &curlUpCallback); - } - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READDATA, new_req->mCurlHandle); - - mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle); - if (mcode > CURLM_OK) - { - // Failure. Deleting the pending request will remove it from the running - // queue, and push it to the end of the pending queue. - new_req->cleanupCurlHandle(); - deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID()); - break; - } - else - { - // Get the uncompressed file size. - LLVFile file(mVFS,new_req->getUUID(),new_req->getType()); - S32 size = file.getSize(); - llinfos << "Requesting PUT " << new_req->mURLBuffer << ", asset size: " << size << " bytes" << llendl; - if (size == 0) - { - llwarns << "Rejecting zero size PUT request!" << llendl; - new_req->cleanupCurlHandle(); - deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID()); - } - } - // Pending upload will have been flagged by the request - } - - while ( (req = findNextRequest(mPendingLocalUploads, mRunningLocalUploads)) ) - { - // setup this curl upload request - LLVFile file(mVFS, req->getUUID(), req->getType()); - - std::string tmp_url; - std::string uuid_str; - req->getUUID().toString(uuid_str); - - // KLW - All temporary uploads are saved locally "http://localhost:12041/asset" - tmp_url = llformat("%s/%36s.%s", mLocalBaseURL.c_str(), uuid_str.c_str(), LLAssetType::lookup(req->getType())); - - LLHTTPAssetRequest *new_req = new LLHTTPAssetRequest(this, req->getUUID(), - req->getType(), RT_LOCALUPLOAD, tmp_url, mCurlMultiHandle); - new_req->mRequestingAgentID = req->mRequestingAgentID; - - // Sets pending upload flag internally - new_req->setupCurlHandle(); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_PUT, 1); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_INFILESIZE, file.getSize()); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_WRITEFUNCTION, &nullOutputCallback); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READFUNCTION, &curlUpCallback); - curl_easy_setopt(new_req->mCurlHandle, CURLOPT_READDATA, new_req->mCurlHandle); - - mcode = curl_multi_add_handle(mCurlMultiHandle, new_req->mCurlHandle); - if (mcode > CURLM_OK) - { - // Failure. Deleting the pending request will remove it from the running - // queue, and push it to the end of the pending queue. - new_req->cleanupCurlHandle(); - deletePendingRequest(RT_LOCALUPLOAD, new_req->getType(), new_req->getUUID()); - break; - } - else - { - // Get the uncompressed file size. - S32 size = file.getSize(); - - llinfos << "TAT: LLHTTPAssetStorage::checkForTimeouts() : pending local!" - << " Requesting PUT " << new_req->mURLBuffer << ", asset size: " << size << " bytes" << llendl; - if (size == 0) - { - - llwarns << "Rejecting zero size PUT request!" << llendl; - new_req->cleanupCurlHandle(); - deletePendingRequest(RT_UPLOAD, new_req->getType(), new_req->getUUID()); - } - - } - // Pending upload will have been flagged by the request - } - S32 count = 0; - int queue_length; - do - { - mcode = curl_multi_perform(mCurlMultiHandle, &queue_length); - count++; - } while (mcode == CURLM_CALL_MULTI_PERFORM && (count < 5)); - - CURLMsg *curl_msg; - do - { - curl_msg = curl_multi_info_read(mCurlMultiHandle, &queue_length); - if (curl_msg && curl_msg->msg == CURLMSG_DONE) - { - long curl_result = 0; - S32 xfer_result = LL_ERR_NOERR; - - LLHTTPAssetRequest *req = NULL; - curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_PRIVATE, &req); - - // TODO: Throw curl_result at all callbacks. - curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_HTTP_CODE, &curl_result); - if (RT_UPLOAD == req->mRequestType || RT_LOCALUPLOAD == req->mRequestType) - { - if (curl_msg->data.result == CURLE_OK && - ( curl_result == HTTP_OK - || curl_result == HTTP_PUT_OK - || curl_result == HTTP_NO_CONTENT)) - { - llinfos << "Success uploading " << req->getUUID() << " to " << req->mURLBuffer << llendl; - if (RT_LOCALUPLOAD == req->mRequestType) - { - addTempAssetData(req->getUUID(), req->mRequestingAgentID, mHostName); - } - } - else if (curl_msg->data.result == CURLE_COULDNT_CONNECT || - curl_msg->data.result == CURLE_OPERATION_TIMEOUTED || - curl_result == HTTP_SERVER_BAD_GATEWAY || - curl_result == HTTP_SERVER_TEMP_UNAVAILABLE) - { - llwarns << "Re-requesting upload for " << req->getUUID() << ". Received upload error to " << req->mURLBuffer << - " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; - - ////HACK (probably) I am sick of this getting requeued and driving me mad. - //if (req->mIsUserWaiting) - //{ - // deletePendingRequest(RT_UPLOAD, req->getType(), req->getUUID()); - //} - } - else - { - llwarns << "Failure uploading " << req->getUUID() << " to " << req->mURLBuffer << - " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; - - xfer_result = LL_ERR_ASSET_REQUEST_FAILED; - } - - if (!(curl_msg->data.result == CURLE_COULDNT_CONNECT || - curl_msg->data.result == CURLE_OPERATION_TIMEOUTED || - curl_result == HTTP_SERVER_BAD_GATEWAY || - curl_result == HTTP_SERVER_TEMP_UNAVAILABLE)) - { - // shared upload finished callback - // in the base class, this is called from processUploadComplete - _callUploadCallbacks(req->getUUID(), req->getType(), (xfer_result == 0), LL_EXSTAT_CURL_RESULT | curl_result); - // Pending upload flag will get cleared when the request is deleted - } - } - else if (RT_DOWNLOAD == req->mRequestType) - { - if (curl_result == HTTP_OK && curl_msg->data.result == CURLE_OK) - { - if (req->mVFile && req->mVFile->getSize() > 0) - { - llinfos << "Success downloading " << req->mURLBuffer << ", size " << req->mVFile->getSize() << llendl; - - req->mVFile->rename(req->getUUID(), req->getType()); - } - else - { - // *TODO: if this actually indicates a bad asset on the server - // (not certain at this point), then delete it - llwarns << "Found " << req->mURLBuffer << " to be zero size" << llendl; - xfer_result = LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE; - } - } - else - { - // KLW - TAT See if an avatar owns this texture, and if so request re-upload. - llwarns << "Failure downloading " << req->mURLBuffer << - " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; - - xfer_result = (curl_result == HTTP_MISSING) ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED; - - if (req->mVFile) - { - req->mVFile->remove(); - } - } - - // call the static callback for transfer completion - // this will cleanup all requests for this asset, including ours - downloadCompleteCallback( - xfer_result, - req->getUUID(), - req->getType(), - (void *)req, - LL_EXSTAT_CURL_RESULT | curl_result); - // Pending download flag will get cleared when the request is deleted - } - else - { - // nothing, just axe this request - // currently this can only mean an asset delete - } - - // Deleting clears the pending upload/download flag if it's set and the request is transferring - delete req; - req = NULL; - } - - } while (curl_msg && queue_length > 0); - - - // Cleanup - // We want to bump to the back of the line any running uploads that have timed out. - bumpTimedOutUploads(); - - LLAssetStorage::checkForTimeouts(); -} - -void LLHTTPAssetStorage::bumpTimedOutUploads() -{ - bool user_waiting=FALSE; - - F64 mt_secs = LLMessageSystem::getMessageTimeSeconds(); - - if (mPendingUploads.size()) - { - request_list_t::iterator it = mPendingUploads.begin(); - LLAssetRequest* req = *it; - user_waiting=req->mIsUserWaiting; - } - - // No point bumping currently running uploads if there are no others in line. - if (!(mPendingUploads.size() > mRunningUploads.size()) && !user_waiting) - { - return; - } - - // deletePendingRequest will modify the mRunningUploads list so we don't want to iterate over it. - request_list_t temp_running = mRunningUploads; - - request_list_t::iterator it = temp_running.begin(); - request_list_t::iterator end = temp_running.end(); - for ( ; it != end; ++it) - { - //request_list_t::iterator curiter = iter++; - LLAssetRequest* req = *it; - - if ( req->mTimeout < (mt_secs - req->mTime) ) - { - llwarns << "Asset upload request timed out for " - << req->getUUID() << "." - << LLAssetType::lookup(req->getType()) - << ", bumping to the back of the line!" << llendl; - - deletePendingRequest(RT_UPLOAD, req->getType(), req->getUUID()); - } - } -} - -// static -size_t LLHTTPAssetStorage::curlDownCallback(void *data, size_t size, size_t nmemb, void *user_data) -{ - if (!gAssetStorage) - { - llwarns << "Missing gAssetStorage, aborting curl download callback!" << llendl; - return 0; - } - S32 bytes = (S32)(size * nmemb); - CURL *curl_handle = (CURL *)user_data; - LLHTTPAssetRequest *req = NULL; - curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req); - - if (! req->mVFile) - { - req->mVFile = new LLVFile(gAssetStorage->mVFS, req->mTmpUUID, LLAssetType::AT_NONE, LLVFile::APPEND); - } - - double content_length = 0.0; - curl_easy_getinfo(curl_handle, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &content_length); - - // sanitize content_length, reconcile w/ actual data - S32 file_length = llmax(0, (S32)llmin(content_length, 20000000.0), bytes + req->mVFile->getSize()); - - req->mVFile->setMaxSize(file_length); - req->mVFile->write((U8*)data, bytes); - - return nmemb; -} - -// static -size_t LLHTTPAssetStorage::curlUpCallback(void *data, size_t size, size_t nmemb, void *user_data) -{ - if (!gAssetStorage) - { - llwarns << "Missing gAssetStorage, aborting curl download callback!" << llendl; - return 0; - } - CURL *curl_handle = (CURL *)user_data; - LLHTTPAssetRequest *req = NULL; - curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req); - - if (! req->mVFile) - { - req->mVFile = new LLVFile(gAssetStorage->mVFS, req->getUUID(), req->getType(), LLVFile::READ); - } - - S32 bytes = llmin((S32)(size * nmemb), (S32)(req->mVFile->getSize() - req->mVFile->tell())); - - req->mVFile->read((U8*)data, bytes);/*Flawfinder: ignore*/ - - return req->mVFile->getLastBytesRead(); -} - -// static -size_t LLHTTPAssetStorage::nullOutputCallback(void *data, size_t size, size_t nmemb, void *user_data) -{ - // do nothing, this is here to soak up script output so it doesn't end up on stdout - - return nmemb; -} - - - -// blocking asset fetch which bypasses the VFS -// this is a very limited function for use by the simstate loader and other one-offs -S32 LLHTTPAssetStorage::getURLToFile(const LLUUID& uuid, LLAssetType::EType asset_type, const std::string &url, const std::string& filename, progress_callback callback, void *userdata) -{ - // *NOTE: There is no guarantee that the uuid and the asset_type match - // - not that it matters. - Doug - lldebugs << "LLHTTPAssetStorage::getURLToFile() - " << url << llendl; - - FILE *fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/ - if (! fp) - { - llwarns << "Failed to open " << filename << " for writing" << llendl; - return LL_ERR_ASSET_REQUEST_FAILED; - } - - // make sure we use the normal curl setup, even though we don't really need a request object - LLHTTPAssetRequest req(this, uuid, asset_type, RT_DOWNLOAD, url, mCurlMultiHandle); - req.mFP = fp; - - req.setupCurlHandle(); - curl_easy_setopt(req.mCurlHandle, CURLOPT_FOLLOWLOCATION, TRUE); - curl_easy_setopt(req.mCurlHandle, CURLOPT_WRITEFUNCTION, &curlFileDownCallback); - curl_easy_setopt(req.mCurlHandle, CURLOPT_WRITEDATA, req.mCurlHandle); - - curl_multi_add_handle(mCurlMultiHandle, req.mCurlHandle); - llinfos << "Requesting as file " << req.mURLBuffer << llendl; - - // braindead curl loop - int queue_length; - CURLMsg *curl_msg; - LLTimer timeout; - timeout.setTimerExpirySec(GET_URL_TO_FILE_TIMEOUT); - bool success = false; - S32 xfer_result = 0; - do - { - curl_multi_perform(mCurlMultiHandle, &queue_length); - curl_msg = curl_multi_info_read(mCurlMultiHandle, &queue_length); - - if (callback) - { - callback(userdata); - } - - if ( curl_msg && (CURLMSG_DONE == curl_msg->msg) ) - { - success = true; - } - else if (timeout.hasExpired()) - { - llwarns << "Request for " << url << " has timed out." << llendl; - success = false; - xfer_result = LL_ERR_ASSET_REQUEST_FAILED; - break; - } - } while (!success); - - if (success) - { - long curl_result = 0; - curl_easy_getinfo(curl_msg->easy_handle, CURLINFO_HTTP_CODE, &curl_result); - - if (curl_result == HTTP_OK && curl_msg->data.result == CURLE_OK) - { - S32 size = ftell(req.mFP); - if (size > 0) - { - // everything seems to be in order - llinfos << "Success downloading " << req.mURLBuffer << " to file, size " << size << llendl; - } - else - { - llwarns << "Found " << req.mURLBuffer << " to be zero size" << llendl; - xfer_result = LL_ERR_ASSET_REQUEST_FAILED; - } - } - else - { - xfer_result = curl_result == HTTP_MISSING ? LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE : LL_ERR_ASSET_REQUEST_FAILED; - llinfos << "Failure downloading " << req.mURLBuffer << - " with result " << curl_easy_strerror(curl_msg->data.result) << ", http result " << curl_result << llendl; - } - } - - fclose(fp); - if (xfer_result) - { - LLFile::remove(filename); - } - return xfer_result; -} - - -// static -size_t LLHTTPAssetStorage::curlFileDownCallback(void *data, size_t size, size_t nmemb, void *user_data) -{ - CURL *curl_handle = (CURL *)user_data; - LLHTTPAssetRequest *req = NULL; - curl_easy_getinfo(curl_handle, CURLINFO_PRIVATE, &req); - - if (! req->mFP) - { - llwarns << "Missing mFP, aborting curl file download callback!" << llendl; - return 0; - } - - return fwrite(data, size, nmemb, req->mFP); -} - -LLAssetStorage::request_list_t* LLHTTPAssetStorage::getRunningList(LLAssetStorage::ERequestType rt) -{ - switch (rt) - { - case RT_DOWNLOAD: - return &mRunningDownloads; - case RT_UPLOAD: - return &mRunningUploads; - case RT_LOCALUPLOAD: - return &mRunningLocalUploads; - default: - return NULL; - } -} - -const LLAssetStorage::request_list_t* LLHTTPAssetStorage::getRunningList(LLAssetStorage::ERequestType rt) const -{ - switch (rt) - { - case RT_DOWNLOAD: - return &mRunningDownloads; - case RT_UPLOAD: - return &mRunningUploads; - case RT_LOCALUPLOAD: - return &mRunningLocalUploads; - default: - return NULL; - } -} - - -void LLHTTPAssetStorage::addRunningRequest(ERequestType rt, LLHTTPAssetRequest* request) -{ - request_list_t* requests = getRunningList(rt); - if (requests) - { - requests->push_back(request); - } - else - { - llerrs << "LLHTTPAssetStorage::addRunningRequest - Request is not an upload OR download, this is bad!" << llendl; - } -} - -void LLHTTPAssetStorage::removeRunningRequest(ERequestType rt, LLHTTPAssetRequest* request) -{ - request_list_t* requests = getRunningList(rt); - if (requests) - { - requests->remove(request); - } - else - { - llerrs << "LLHTTPAssetStorage::removeRunningRequest - Destroyed request is not an upload OR download, this is bad!" << llendl; - } -} - -// virtual -void LLHTTPAssetStorage::addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name) -{ - if (agent_id.isNull() || asset_id.isNull()) - { - llwarns << "TAT: addTempAssetData bad id's asset_id: " << asset_id << " agent_id: " << agent_id << llendl; - return; - } - - LLTempAssetData temp_asset_data; - temp_asset_data.mAssetID = asset_id; - temp_asset_data.mAgentID = agent_id; - temp_asset_data.mHostName = host_name; - - mTempAssets[asset_id] = temp_asset_data; -} - -// virtual -BOOL LLHTTPAssetStorage::hasTempAssetData(const LLUUID& texture_id) const -{ - uuid_tempdata_map::const_iterator citer = mTempAssets.find(texture_id); - BOOL found = (citer != mTempAssets.end()); - return found; -} - -// virtual -std::string LLHTTPAssetStorage::getTempAssetHostName(const LLUUID& texture_id) const -{ - uuid_tempdata_map::const_iterator citer = mTempAssets.find(texture_id); - if (citer != mTempAssets.end()) - { - return citer->second.mHostName; - } - else - { - return std::string(); - } -} - -// virtual -LLUUID LLHTTPAssetStorage::getTempAssetAgentID(const LLUUID& texture_id) const -{ - uuid_tempdata_map::const_iterator citer = mTempAssets.find(texture_id); - if (citer != mTempAssets.end()) - { - return citer->second.mAgentID; - } - else - { - return LLUUID::null; - } -} - -// virtual -void LLHTTPAssetStorage::removeTempAssetData(const LLUUID& asset_id) -{ - mTempAssets.erase(asset_id); -} - -// virtual -void LLHTTPAssetStorage::removeTempAssetDataByAgentID(const LLUUID& agent_id) -{ - uuid_tempdata_map::iterator it = mTempAssets.begin(); - uuid_tempdata_map::iterator end = mTempAssets.end(); - - while (it != end) - { - const LLTempAssetData& asset_data = it->second; - if (asset_data.mAgentID == agent_id) - { - mTempAssets.erase(it++); - } - else - { - ++it; - } - } -} - -std::string LLHTTPAssetStorage::getBaseURL(const LLUUID& asset_id, LLAssetType::EType asset_type) -{ - if (LLAssetType::AT_TEXTURE == asset_type) - { - uuid_tempdata_map::const_iterator citer = mTempAssets.find(asset_id); - if (citer != mTempAssets.end()) - { - const std::string& host_name = citer->second.mHostName; - std::string url = llformat(LOCAL_ASSET_URL_FORMAT, host_name.c_str()); - return url; - } - } - - return mBaseURL; -} - -void LLHTTPAssetStorage::dumpTempAssetData(const LLUUID& avatar_id) const -{ - uuid_tempdata_map::const_iterator it = mTempAssets.begin(); - uuid_tempdata_map::const_iterator end = mTempAssets.end(); - S32 count = 0; - for ( ; it != end; ++it) - { - const LLTempAssetData& temp_asset_data = it->second; - if (avatar_id.isNull() - || avatar_id == temp_asset_data.mAgentID) - { - llinfos << "TAT: dump agent " << temp_asset_data.mAgentID - << " texture " << temp_asset_data.mAssetID - << " host " << temp_asset_data.mHostName - << llendl; - count++; - } - } - - if (avatar_id.isNull()) - { - llinfos << "TAT: dumped " << count << " entries for all avatars" << llendl; - } - else - { - llinfos << "TAT: dumped " << count << " entries for avatar " << avatar_id << llendl; - } -} - -void LLHTTPAssetStorage::clearTempAssetData() -{ - llinfos << "TAT: Clearing temp asset data map" << llendl; - mTempAssets.clear(); -} diff --git a/indra/llmessage/llhttpassetstorage.h b/indra/llmessage/llhttpassetstorage.h deleted file mode 100644 index f743ccf0a..000000000 --- a/indra/llmessage/llhttpassetstorage.h +++ /dev/null @@ -1,159 +0,0 @@ -/** - * @file llhttpassetstorage.h - * @brief Class for loading asset data to/from an external source over http. - * - * $LicenseInfo:firstyear=2003&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LLHTTPASSETSTORAGE_H -#define LLHTTPASSETSTORAGE_H - -#include "llassetstorage.h" -#include "curl/curl.h" - -class LLVFile; -class LLHTTPAssetRequest; -typedef void (*progress_callback)(void* userdata); - -struct LLTempAssetData; - -typedef std::map uuid_tempdata_map; - -class LLHTTPAssetStorage : public LLAssetStorage -{ -public: - LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, - LLVFS *vfs, LLVFS *static_vfs, - const LLHost &upstream_host, - const std::string& web_host, - const std::string& local_web_host, - const std::string& host_name); - - LLHTTPAssetStorage(LLMessageSystem *msg, LLXferManager *xfer, - LLVFS *vfs, LLVFS *static_vfs, - const std::string& web_host, - const std::string& local_web_host, - const std::string& host_name); - - - virtual ~LLHTTPAssetStorage(); - - using LLAssetStorage::storeAssetData; // Unhiding virtuals... - - virtual void storeAssetData( - const LLUUID& uuid, - LLAssetType::EType atype, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file = false, - bool is_priority = false, - bool store_local = false, - const LLUUID& requesting_agent_id = LLUUID::null, - bool user_waiting=FALSE, - F64 timeout=LL_ASSET_STORAGE_TIMEOUT); - - virtual void storeAssetData( - const std::string& filename, - const LLUUID& asset_id, - LLAssetType::EType atype, - LLStoreAssetCallback callback, - void* user_data, - bool temp_file, - bool is_priority, - bool user_waiting=FALSE, - F64 timeout=LL_ASSET_STORAGE_TIMEOUT); - - virtual LLSD getPendingDetails(ERequestType rt, - LLAssetType::EType asset_type, - const std::string& detail_prefix) const; - - virtual LLSD getPendingRequest(ERequestType rt, - LLAssetType::EType asset_type, - const LLUUID& asset_id) const; - - virtual bool deletePendingRequest(ERequestType rt, - LLAssetType::EType asset_type, - const LLUUID& asset_id); - - // Hack. One off curl download an URL to a file. Probably should be elsewhere. - // Only used by lldynamicstate. The API is broken, and should be replaced with - // a generic HTTP file fetch - Doug 9/25/06 - S32 getURLToFile(const LLUUID& uuid, LLAssetType::EType asset_type, const std::string &url, const std::string& filename, progress_callback callback, void *userdata); - - LLAssetRequest* findNextRequest(request_list_t& pending, request_list_t& running); - - void checkForTimeouts(); - - static size_t curlDownCallback(void *data, size_t size, size_t nmemb, void *user_data); - static size_t curlFileDownCallback(void *data, size_t size, size_t nmemb, void *user_data); - static size_t curlUpCallback(void *data, size_t size, size_t nmemb, void *user_data); - static size_t nullOutputCallback(void *data, size_t size, size_t nmemb, void *user_data); - - // Should only be used by the LLHTTPAssetRequest - void addRunningRequest(ERequestType rt, LLHTTPAssetRequest* request); - void removeRunningRequest(ERequestType rt, LLHTTPAssetRequest* request); - - request_list_t* getRunningList(ERequestType rt); - const request_list_t* getRunningList(ERequestType rt) const; - - // Temp assets are stored on sim nodes, they have agent ID and location data associated with them. - virtual void addTempAssetData(const LLUUID& asset_id, const LLUUID& agent_id, const std::string& host_name); - virtual BOOL hasTempAssetData(const LLUUID& texture_id) const; - virtual std::string getTempAssetHostName(const LLUUID& texture_id) const; - virtual LLUUID getTempAssetAgentID(const LLUUID& texture_id) const; - virtual void removeTempAssetData(const LLUUID& asset_id); - virtual void removeTempAssetDataByAgentID(const LLUUID& agent_id); - - // Pass LLUUID::null for all - virtual void dumpTempAssetData(const LLUUID& avatar_id) const; - virtual void clearTempAssetData(); - -protected: - void _queueDataRequest(const LLUUID& uuid, LLAssetType::EType type, - void (*callback)(LLVFS *vfs, const LLUUID&, LLAssetType::EType, void *, S32, LLExtStat), - void *user_data, BOOL duplicate, BOOL is_priority); - -private: - void _init(const std::string& web_host, const std::string& local_web_host, const std::string& host_name); - - // This will return the correct base URI for any http asset request - std::string getBaseURL(const LLUUID& asset_id, LLAssetType::EType asset_type); - - // Check for running uploads that have timed out - // Bump these to the back of the line to let other uploads complete. - void bumpTimedOutUploads(); - -protected: - std::string mBaseURL; - std::string mLocalBaseURL; - std::string mHostName; - - CURLM *mCurlMultiHandle; - - request_list_t mRunningDownloads; - request_list_t mRunningUploads; - request_list_t mRunningLocalUploads; - - uuid_tempdata_map mTempAssets; -}; - -#endif diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp index b9cddc8e4..090ab2a00 100644 --- a/indra/llmessage/llxfermanager.cpp +++ b/indra/llmessage/llxfermanager.cpp @@ -261,7 +261,7 @@ U32 LLXferManager::numActiveListEntries(LLXfer *list_head) while (list_head) { - if ((list_head->mStatus == e_LL_XFER_IN_PROGRESS)) + if (list_head->mStatus == e_LL_XFER_IN_PROGRESS) { num_entries++; } diff --git a/indra/llplugin/llplugininstance.cpp b/indra/llplugin/llplugininstance.cpp index 15e1d347a..793c8bb97 100644 --- a/indra/llplugin/llplugininstance.cpp +++ b/indra/llplugin/llplugininstance.cpp @@ -99,7 +99,22 @@ int LLPluginInstance::load(std::string &plugin_file) if(result != APR_SUCCESS) { char buf[1024]; - apr_dso_error(mDSOHandle, buf, sizeof(buf)); +#if LL_LINUX && defined(LL_STANDALONE) + if (!dso_handle) + { + char* error = dlerror(); + buf[0] = 0; + if (error) + { + strncpy(buf, dlerror(), sizeof(buf)); + } + buf[sizeof(buf) - 1] = 0; + } + else +#endif + { + apr_dso_error(mDSOHandle, buf, sizeof(buf)); + } #if LL_LINUX && defined(LL_STANDALONE) LL_WARNS("Plugin") << "plugin load " << plugin_file << " failed with error " << result << " , additional info string: " << buf << LL_ENDL; diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp index 04662cf24..b841a30e1 100644 --- a/indra/llplugin/slplugin/slplugin.cpp +++ b/indra/llplugin/slplugin/slplugin.cpp @@ -191,7 +191,7 @@ int main(int argc, char **argv) #ifdef CWDEBUG Debug( libcw_do.margin().assign("SLPlugin ", 9) ); Debug(debug::init()); - // Uncomment this to automatically open a terminal with gdb. Requires SNOW-173. + // Uncomment this to automatically open a terminal with gdb. //Debug(attach_gdb()); #endif diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index c7e58aff9..06f6155c9 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -429,6 +429,7 @@ public: virtual void placeFence() = 0; virtual bool isCompleted() = 0; virtual void wait() = 0; + virtual ~LLGLFence() {} }; class LLGLSyncFence : public LLGLFence diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 696730924..de2843db4 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -1400,13 +1400,13 @@ void LLVertexBuffer::setupVertexArray() //glVertexattribIPointer requires GLSL 1.30 or later if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30) { - glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], (void*) mOffsets[i]); + glVertexAttribIPointer(i, attrib_size[i], attrib_type[i], sTypeSize[i], reinterpret_cast(mOffsets[i])); } #endif } else { - glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], (void*) mOffsets[i]); + glVertexAttribPointerARB(i, attrib_size[i], attrib_type[i], attrib_normalized[i], sTypeSize[i], reinterpret_cast(mOffsets[i])); } } else diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp index a0f319a90..0d1c4b37f 100644 --- a/indra/llvfs/lldiriterator.cpp +++ b/indra/llvfs/lldiriterator.cpp @@ -133,7 +133,7 @@ bool LLDirIterator::Impl::next(std::string &fname) #else std::string name = mIter->path().filename(); #endif - if (found = boost::regex_match(name, match, mFilterExp)) + if ((found = boost::regex_match(name, match, mFilterExp))) { fname = name; } diff --git a/indra/newview/jcfloaterareasearch.cpp b/indra/newview/jcfloaterareasearch.cpp index 57ad0bebd..3cb15b052 100644 --- a/indra/newview/jcfloaterareasearch.cpp +++ b/indra/newview/jcfloaterareasearch.cpp @@ -52,7 +52,7 @@ std::string JCFloaterAreaSearch::sSearchedDesc; std::string JCFloaterAreaSearch::sSearchedOwner; std::string JCFloaterAreaSearch::sSearchedGroup; -const std::string request_string = "JCFloaterAreaSearch::Requested_ø§µ"; +const std::string request_string = "JCFloaterAreaSearch::Requested_\xF8\xA7\xB5"; const F32 min_refresh_interval = 0.25f; // Minimum interval between list refreshes in seconds. JCFloaterAreaSearch::JCFloaterAreaSearch() : diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 44994b59a..08c35ec43 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -2896,7 +2896,7 @@ void LLAgentCamera::lookAtObject(const LLUUID &object_id, bool self) BOOL LLAgentCamera::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position) { // disallow pointing at attachments and avatars - if (object && (object->isAttachment() || object->isAvatar()) || gSavedSettings.getBOOL("DisablePointAtAndBeam")) + if ((object && (object->isAttachment() || object->isAvatar())) || gSavedSettings.getBOOL("DisablePointAtAndBeam")) { return FALSE; } diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 60ebf402e..4cab987ae 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -3428,7 +3428,7 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b //to cause appearance of the agent to be updated bool result = false; - if (result = gAgentWearables.moveWearable(item, closer_to_body)) + if ((result = gAgentWearables.moveWearable(item, closer_to_body))) { gAgentAvatarp->wearableUpdated(item->getWearableType(), FALSE); } diff --git a/indra/newview/llappviewerlinux_api_dbus.cpp b/indra/newview/llappviewerlinux_api_dbus.cpp index b475eeedb..656a7444a 100644 --- a/indra/newview/llappviewerlinux_api_dbus.cpp +++ b/indra/newview/llappviewerlinux_api_dbus.cpp @@ -38,6 +38,7 @@ #endif #include "linden_common.h" +#include "llaprpool.h" extern "C" { #include @@ -55,8 +56,8 @@ extern "C" { #undef LL_DBUS_SYM static bool sSymsGrabbed = false; -static apr_pool_t *sSymDBUSDSOMemoryPool = NULL; -static apr_dso_handle_t *sSymDBUSDSOHandleG = NULL; +static LLAPRPool sSymDBUSDSOMemoryPool; // Used for sSymDBUSDSOHandleG (and what it is pointing at?) +static apr_dso_handle_t* sSymDBUSDSOHandleG = NULL; bool grab_dbus_syms(std::string dbus_dso_name) { @@ -74,18 +75,18 @@ bool grab_dbus_syms(std::string dbus_dso_name) #define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##DBUSSYM, sSymDBUSDSOHandle, #DBUSSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #DBUSSYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #DBUSSYM, (void*)ll##DBUSSYM);}while(0) //attempt to load the shared library - apr_pool_create(&sSymDBUSDSOMemoryPool, NULL); + sSymDBUSDSOMemoryPool.create(); #ifdef LL_STANDALONE void *dso_handle = dlopen(dbus_dso_name.c_str(), RTLD_NOW | RTLD_GLOBAL); rv = (!dso_handle)?APR_EDSOOPEN:apr_os_dso_handle_put(&sSymDBUSDSOHandle, - dso_handle, sSymDBUSDSOMemoryPool); + dso_handle, sSymDBUSDSOMemoryPool()); if ( APR_SUCCESS == rv ) #else if ( APR_SUCCESS == (rv = apr_dso_load(&sSymDBUSDSOHandle, dbus_dso_name.c_str(), - sSymDBUSDSOMemoryPool) )) + sSymDBUSDSOMemoryPool()) )) #endif { INFOMSG("Found DSO: %s", dbus_dso_name.c_str()); @@ -113,6 +114,10 @@ bool grab_dbus_syms(std::string dbus_dso_name) #undef LL_DBUS_SYM sSymsGrabbed = rtn; + if (!sSymsGrabbed) + { + sSymDBUSDSOMemoryPool.destroy(); + } return rtn; } @@ -127,13 +132,9 @@ void ungrab_dbus_syms() apr_dso_unload(sSymDBUSDSOHandleG); sSymDBUSDSOHandleG = NULL; } - - if ( sSymDBUSDSOMemoryPool ) - { - apr_pool_destroy(sSymDBUSDSOMemoryPool); - sSymDBUSDSOMemoryPool = NULL; - } - + + sSymDBUSDSOMemoryPool.destroy(); + // NULL-out all of the symbols we'd grabbed #define LL_DBUS_SYM(REQUIRED, DBUSSYM, RTN, ...) do{ll##DBUSSYM = NULL;}while(0) #include "llappviewerlinux_api_dbus_syms_raw.inc" diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 56c372655..a37f117c4 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -1438,7 +1438,7 @@ void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) { - if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled()) + if ((avatar->isSelf() && !gAgent.needsRenderAvatar()) || !gMeshRepo.meshRezEnabled()) { return; } diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 828ad5689..42a4f5c46 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -424,7 +424,7 @@ void LLInventoryFilter::setFilterSubString(const std::string& string) if (mFilterOps.mFilterTypes == FILTERTYPE_UUID) { mFilterOps.mFilterTypes &= ~FILTERTYPE_UUID; - mFilterOps.mFilterUUID == LLUUID::null; + //mFilterOps.mFilterUUID == LLUUID::null; setModified(FILTER_RESTART); } @@ -519,8 +519,8 @@ void LLInventoryFilter::setHoursAgo(U32 hours) bool is_increasing_from_zero = is_increasing && !mFilterOps.mHoursAgo; // *NOTE: need to cache last filter time, in case filter goes stale - BOOL less_restrictive = (are_date_limits_valid && ((is_increasing && mFilterOps.mHoursAgo)) || !hours); - BOOL more_restrictive = (are_date_limits_valid && (!is_increasing && hours) || is_increasing_from_zero); + BOOL less_restrictive = ((are_date_limits_valid && ((is_increasing && mFilterOps.mHoursAgo))) || !hours); + BOOL more_restrictive = ((are_date_limits_valid && (!is_increasing && hours)) || is_increasing_from_zero); mFilterOps.mHoursAgo = hours; mFilterOps.mMinDate = time_min(); diff --git a/indra/newview/llpanellandmedia.cpp b/indra/newview/llpanellandmedia.cpp index 417d14897..e49e849a0 100644 --- a/indra/newview/llpanellandmedia.cpp +++ b/indra/newview/llpanellandmedia.cpp @@ -120,31 +120,12 @@ BOOL LLPanelLandMedia::postBuild() childSetCommitCallback("media_size_height", onCommitAny, this); mMediaSizeCtrlLabel = getChild("media_size"); - /*mMediaNavigateAllowCheck = getChild("check navigate allow"); Making Dummy View -HgB - childSetCommitCallback("check navigate allow", onCommitAny, this);*/ - mMediaURLFilterCheck = getChild("check navigate filter"); - childSetCommitCallback("check navigate filter", onCommitAny, this); - mSetURLButton = getChild("set_media_url"); childSetAction("set_media_url", onSetBtn, this); mResetURLButton = getChild("reset_media_url"); childSetAction("reset_media_url", onResetBtn, this); - mURLFilterList = getChild("filter_list"); - - mMediaURLFilterDomainEdit = getChild("navigate_filter_domain"); - - mMediaURLFilterAddButton = getChild("add_navigate_filter"); - childSetAction("add_navigate_filter", onClickAddURLFilter, this); - - mMediaURLFilterRemoveButton = getChild("remove_navigate_filter"); - childSetAction("remove_navigate_filter", onClickRemoveURLFilter, this); - - mRadioNavigateControl = getChild("radio_navigate_allow"); - childSetCommitCallback("radio_navigate_allow", onCommitAny, this); - - return TRUE; } @@ -222,43 +203,11 @@ void LLPanelLandMedia::refresh() mSetURLButton->setEnabled( can_change_media ); mResetURLButton->setEnabled( can_change_media ); - mMediaURLFilterCheck->set( parcel->getMediaURLFilterEnable() ); - mMediaURLFilterCheck->setEnabled( can_change_media ); - LLFloaterURLEntry* floater_url_entry = (LLFloaterURLEntry*)mURLEntryFloater.get(); if (floater_url_entry) { floater_url_entry->updateFromLandMediaPanel(); } - - // This radial control is really just an inverse mapping to the boolean allow_navigate value. - // It is set as a radial merely for user readability. - mRadioNavigateControl->setSelectedIndex(! parcel->getMediaAllowNavigate()); - mRadioNavigateControl->setEnabled( can_change_media ); - - mMediaURLFilterDomainEdit->setEnabled( can_change_media ); - mMediaURLFilterAddButton->setEnabled( can_change_media ); - mMediaURLFilterRemoveButton->setEnabled( can_change_media ); - - if (mURLFilterList) - { - mURLFilterList->setEnabled( can_change_media ); - - mURLFilterList->deleteAllItems(); - - LLSD list = parcel->getMediaURLFilterList(); - - for (LLSD::array_iterator i = list.beginArray(); i != list.endArray(); ++i) - { - std::string domain = (*i).asString(); - - LLSD element; - element["id"] = domain; - element["columns"][0]["value"] = domain; - - mURLFilterList->addElement(element); - } - } } } @@ -281,8 +230,7 @@ void LLPanelLandMedia::populateMIMECombo() mMediaTypeCombo->add(info.mLabel, mime_type); } } - // *TODO: The sort order is based on std::map key, which is - // ASCII-sorted and is wrong in other languages. TRANSLATE + mMediaTypeCombo->add( default_label, default_mime_type, ADD_BOTTOM ); } @@ -341,17 +289,15 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata) } // Extract data from UI - std::string media_url = self->mMediaURLEdit->getText(); - std::string media_desc = self->mMediaDescEdit->getText(); - std::string mime_type = self->childGetText("mime_type"); + std::string media_url = self->mMediaURLEdit->getText(); + std::string media_desc = self->mMediaDescEdit->getText(); + std::string mime_type = self->childGetText("mime_type"); U8 media_auto_scale = self->mMediaAutoScaleCheck->get(); - U8 media_loop = self->mMediaLoopCheck->get(); - F32 media_reset_time = (F32)self->mMediaResetCtrl->get(); + U8 media_loop = self->mMediaLoopCheck->get(); + F32 media_reset_time = (F32)self->mMediaResetCtrl->get(); S32 media_width = (S32)self->mMediaWidthCtrl->get(); S32 media_height = (S32)self->mMediaHeightCtrl->get(); LLUUID media_id = self->mMediaTextureCtrl->getImageAssetID(); - U8 navigate_allow = ! self->mRadioNavigateControl->getSelectedIndex(); - U8 navigate_filter = self->mMediaURLFilterCheck->get(); self->childSetText("mime_type", mime_type); @@ -368,8 +314,6 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl*, void *userdata) parcel->setMediaID(media_id); parcel->setMediaAutoScale ( media_auto_scale ); parcel->setMediaLoop ( media_loop ); - parcel->setMediaURLFilterEnable(navigate_filter); - parcel->setMediaAllowNavigate(navigate_allow); parcel->setMediaURLTimeout(media_reset_time); @@ -402,79 +346,3 @@ void LLPanelLandMedia::onResetBtn(void *userdata) // LLViewerParcelMedia::sendMediaNavigateMessage(parcel->getMediaURL()); } -// static -void LLPanelLandMedia::onClickAddURLFilter(void *userdata) -{ - LLPanelLandMedia *panelp = (LLPanelLandMedia *)userdata; - LLParcel* parcel = panelp->mParcel->getParcel(); - - LLSD list = parcel->getMediaURLFilterList(); - - std::string domain = panelp->mMediaURLFilterDomainEdit->getText(); - LLStringUtil::trim(domain); - - BOOL add = TRUE; - if (domain == "") - { - add = FALSE; - } - - // check for dupes - for(S32 i = 0; i < list.size(); i++) - { - if (list[i].asString() == domain) - { - add = FALSE; - break; - } - } - - if (add) - { - list.append(domain); - parcel->setMediaURLFilterList(list); - - LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); - - panelp->mMediaURLFilterDomainEdit->setText(std::string("")); - - panelp->refresh(); - } - -} - -// static -void LLPanelLandMedia::onClickRemoveURLFilter(void *data) -{ - LLPanelLandMedia* panelp = (LLPanelLandMedia*)data; - if (panelp && panelp->mURLFilterList) - { - LLParcel* parcel = panelp->mParcel->getParcel(); - if (parcel) - { - LLSD list = parcel->getMediaURLFilterList(); - - std::vector domains = panelp->mURLFilterList->getAllSelected(); - for (std::vector::iterator iter = domains.begin(); iter != domains.end(); iter++) - { - LLScrollListItem* item = *iter; - const std::string domain = item->getValue().asString(); - - for(S32 i = 0; i < list.size(); i++) - { - if (list[i].asString() == domain) - { - list.erase(i); - break; - } - } - } - - parcel->setMediaURLFilterList(list); - LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel ); - - panelp->refresh(); - } - } - -} diff --git a/indra/newview/llpanellandmedia.h b/indra/newview/llpanellandmedia.h index c883d9801..6f9d9bb54 100644 --- a/indra/newview/llpanellandmedia.h +++ b/indra/newview/llpanellandmedia.h @@ -57,8 +57,6 @@ private: static void onCommitType(LLUICtrl* ctrl, void *userdata); static void onSetBtn(void* userdata); static void onResetBtn(void* userdata); - static void onClickAddURLFilter(void *userdata); - static void onClickRemoveURLFilter(void *userdata); private: LLLineEditor* mMediaURLEdit; @@ -76,15 +74,6 @@ private: LLCheckBoxCtrl* mMediaLoopCheck; LLCheckBoxCtrl* mMediaUrlCheck; LLHandle mURLEntryFloater; - LLCheckBoxCtrl* mMediaNavigateAllowCheck; - LLCheckBoxCtrl* mMediaURLFilterCheck; - LLLineEditor* mMediaURLFilterDomainEdit; - LLButton* mMediaURLFilterAddButton; - LLButton* mMediaURLFilterRemoveButton; - LLScrollListCtrl* mURLFilterList; - LLRadioGroup* mRadioNavigateControl; - - LLSafeHandle& mParcel; }; diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 7843a9e97..fc78ecae6 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -478,10 +478,10 @@ void LLPanelObject::getState( ) } // can move or rotate only linked group with move permissions, or sub-object with move and modify perms - BOOL enable_move = objectp->permMove() && (!objectp->isAttachment() && objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + BOOL enable_move = objectp->permMove() && ((!objectp->isAttachment() && objectp->permModify()) || !gSavedSettings.getBOOL("EditLinkedParts")); BOOL enable_scale = objectp->permMove() && objectp->permModify(); - BOOL enable_rotate = objectp->permMove() && ( (objectp->permModify() && !objectp->isAttachment()) || !gSavedSettings.getBOOL("EditLinkedParts")); - BOOL enable_link = objectp->permMove() && !objectp->isAttachment() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + BOOL enable_rotate = objectp->permMove() && ((objectp->permModify() && !objectp->isAttachment()) || !gSavedSettings.getBOOL("EditLinkedParts")); + BOOL enable_link = objectp->permMove() && ((!objectp->isAttachment() && objectp->permModify()) || !gSavedSettings.getBOOL("EditLinkedParts")); childSetEnabled("build_math_constants",true); S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME )) diff --git a/indra/newview/llpreviewsound.cpp b/indra/newview/llpreviewsound.cpp index c88cc1cc6..e1832477a 100644 --- a/indra/newview/llpreviewsound.cpp +++ b/indra/newview/llpreviewsound.cpp @@ -146,7 +146,7 @@ void LLPreviewSound::playAmbient( void* userdata ) if(item && gAudiop) { - int gain = 0.01f; + F32 gain = 0.01f; for(int i = 0; i < 2; i++) { gMessageSystem->newMessageFast(_PREHASH_SoundTrigger); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4a28e53a9..18aaabef4 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -660,17 +660,6 @@ bool idle_startup() { gAudiop = NULL; -#ifdef LL_OPENAL - if (!gAudiop -#if !LL_WINDOWS - && NULL == getenv("LL_BAD_OPENAL_DRIVER") -#endif // !LL_WINDOWS - ) - { - gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); - } -#endif - #ifdef LL_FMODEX if (!gAudiop #if !LL_WINDOWS @@ -682,6 +671,17 @@ bool idle_startup() } #endif +#ifdef LL_OPENAL + if (!gAudiop +#if !LL_WINDOWS + && NULL == getenv("LL_BAD_OPENAL_DRIVER") +#endif // !LL_WINDOWS + ) + { + gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); + } +#endif + #ifdef LL_FMOD if (!gAudiop #if !LL_WINDOWS diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index bacfa4938..7d9f0a136 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -675,7 +675,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask) const LLPickInfo& pick = gViewerWindow->getHoverPick(); object = pick.getObject(); if ( (object) && (rlv_handler_t::isEnabled()) && - ( ((gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH))) && (!gRlvHandler.canTouch(object, pick.mObjectOffset)) || + ( (((gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH))) && (!gRlvHandler.canTouch(object, pick.mObjectOffset))) || ((gRlvHandler.hasBehaviour(RLV_BHVR_INTERACT)) && (!object->isHUDAttachment())) ) ) { gViewerWindow->getWindow()->setCursor(UI_CURSOR_ARROW); diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 3200caa0f..adadcd799 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -87,7 +87,7 @@ BOOL gHackGodmode = FALSE; #endif -AITHREADSAFE(settings_map_type, gSettings,); +AIThreadSafeDC gSettings; LLControlGroup gSavedSettings("Global"); // saved at end of session LLControlGroup gSavedPerAccountSettings("PerAccount"); // saved at end of session LLControlGroup gColors("Colors"); // saved at end of session diff --git a/indra/newview/llviewercontrol.h b/indra/newview/llviewercontrol.h index df4313ef0..d8bdf3670 100644 --- a/indra/newview/llviewercontrol.h +++ b/indra/newview/llviewercontrol.h @@ -51,7 +51,7 @@ extern BOOL gHackGodmode; void settings_setup_listeners(); typedef std::map settings_map_type; -extern AIThreadSafe gSettings; +extern AIThreadSafeDC gSettings; // for the graphics settings void create_graphics_group(LLControlGroup& group); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 266362ae8..d30b40ff8 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5332,7 +5332,7 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) if (object) { LLVector3 sit_spot = object->getPositionAgent() + (sitPosition * object->getRotation()); - if (!use_autopilot || isAgentAvatarValid() && gAgentAvatarp->isSitting() && gAgentAvatarp->getRoot() == object->getRoot()) + if (!use_autopilot || (isAgentAvatarValid() && gAgentAvatarp->isSitting() && gAgentAvatarp->getRoot() == object->getRoot())) { //we're already sitting on this object, so don't autopilot } diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index 1493f4abb..149549c0f 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -762,7 +762,7 @@ void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type) if (media_url.empty()) { - media_action == "allow"; + media_action = "allow"; } else if (!sMediaFilterListLoaded || sDeniedMedia.count(domain) || sDeniedMedia.count(ip)) { diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 64f20ff50..a15722cda 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1678,9 +1678,6 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use // Request access list information for this land parcel_mgr.sendParcelAccessListRequest(AL_ACCESS | AL_BAN); - // Request the media url filter list for this land - parcel_mgr.requestParcelMediaURLFilter(); - // Request dwell for this land, if it's not public land. parcel_mgr.mSelectedDwell = 0.f; if (0 != local_id) @@ -2010,67 +2007,6 @@ void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which) } } -class LLParcelMediaURLFilterResponder : public LLHTTPClient::Responder -{ - virtual void result(const LLSD& content) - { - LLViewerParcelMgr::getInstance()->receiveParcelMediaURLFilter(content); - } -}; - -void LLViewerParcelMgr::requestParcelMediaURLFilter() -{ - if (!mSelected) - { - return; - } - - LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth ); - if (!region) - { - return; - } - - LLParcel* parcel = mCurrentParcel; - if (!parcel) - { - llwarns << "no parcel" << llendl; - return; - } - - LLSD body; - body["local-id"] = parcel->getLocalID(); - body["list"] = parcel->getMediaURLFilterList(); - - std::string url = region->getCapability("ParcelMediaURLFilterList"); - if (!url.empty()) - { - LLHTTPClient::post(url, body, new LLParcelMediaURLFilterResponder); - } - else - { - llwarns << "can't get ParcelMediaURLFilterList cap" << llendl; - } -} - - -void LLViewerParcelMgr::receiveParcelMediaURLFilter(const LLSD &content) -{ - if (content.has("list")) - { - LLParcel* parcel = LLViewerParcelMgr::getInstance()->mCurrentParcel; - if (!parcel) return; - - if (content["local-id"].asInteger() == parcel->getLocalID()) - { - parcel->setMediaURLFilterList(content["list"]); - - LLViewerParcelMgr::getInstance()->notifyObservers(); - } - } -} - - void LLViewerParcelMgr::deedLandToGroup() { std::string group_name; diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index c65f57b46..72531ff55 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -227,11 +227,6 @@ public: // Takes an Access List flag, like AL_ACCESS or AL_BAN void sendParcelAccessListRequest(U32 flags); - // asks for the parcel's media url filter list - void requestParcelMediaURLFilter(); - // receive the response - void receiveParcelMediaURLFilter(const LLSD &content); - // Dwell is not part of the usual parcel update information because the // simulator doesn't actually know the per-parcel dwell. Ack! We have // to get it out of the database. diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 37af34e02..6755005a8 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1598,7 +1598,6 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) #endif //MESH_IMPORT capabilityNames.append("NewFileAgentInventory"); capabilityNames.append("ParcelPropertiesUpdate"); - capabilityNames.append("ParcelMediaURLFilterList"); capabilityNames.append("ParcelNavigateMedia"); capabilityNames.append("ParcelVoiceInfoRequest"); capabilityNames.append("ProductInfoRequest"); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 1ae31e9b3..d02641c7a 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -3500,8 +3500,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) continue; } - if (vobj->isMesh() && - (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) + if ((vobj->isMesh() && + (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) { continue; } diff --git a/indra/newview/skins/default/xui/en-us/floater_about_land.xml b/indra/newview/skins/default/xui/en-us/floater_about_land.xml index 08a6c38f7..0cdb416c2 100644 --- a/indra/newview/skins/default/xui/en-us/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en-us/floater_about_land.xml @@ -911,7 +911,7 @@ Only large parcels can be listed in search. height="16" left="10" length="1" - name="at URL2:" + name="at URL2:" type="string" width="65"> Current URL: @@ -1147,146 +1147,6 @@ Select the thumbnail to choose a different texture. width="70"> pixels - - Interaction: - - - - Anyone - - - Group - - - - -