diff options
Diffstat (limited to 'indra/llcommon')
-rwxr-xr-x | indra/llcommon/CMakeLists.txt | 1 | ||||
-rwxr-xr-x | indra/llcommon/llerror.cpp | 444 | ||||
-rwxr-xr-x | indra/llcommon/llerror.h | 4 | ||||
-rwxr-xr-x | indra/llcommon/llerrorcontrol.h | 23 | ||||
-rwxr-xr-x | indra/llcommon/llhttpstatuscodes.h | 89 | ||||
-rwxr-xr-x | indra/llcommon/llinitparam.h | 3 | ||||
-rwxr-xr-x | indra/llcommon/llpointer.h | 126 | ||||
-rwxr-xr-x | indra/llcommon/llsd.cpp | 11 | ||||
-rwxr-xr-x | indra/llcommon/llsd.h | 5 | ||||
-rwxr-xr-x | indra/llcommon/llsdserialize.cpp | 67 | ||||
-rwxr-xr-x | indra/llcommon/llsdserialize.h | 28 | ||||
-rwxr-xr-x | indra/llcommon/llsdserialize_xml.cpp | 17 | ||||
-rwxr-xr-x | indra/llcommon/llsdutil.cpp | 2 | ||||
-rwxr-xr-x | indra/llcommon/llsys.cpp | 2 | ||||
-rwxr-xr-x | indra/llcommon/lluuid.h | 13 | ||||
-rwxr-xr-x | indra/llcommon/tests/llerror_test.cpp | 78 | ||||
-rwxr-xr-x | indra/llcommon/tests/stringize_test.cpp | 2 | ||||
-rwxr-xr-x | indra/llcommon/tests/wrapllerrs.h | 117 |
18 files changed, 590 insertions, 442 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 6433f3379b..5514ea84a8 100755 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -160,7 +160,6 @@ set(llcommon_HEADER_FILES llhandle.h llhash.h llheartbeat.h - llhttpstatuscodes.h llindexedvector.h llinitparam.h llinstancetracker.h diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index a7963174ad..22cd861c72 100755 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -47,6 +47,7 @@ #include "lllivefile.h" #include "llsd.h" #include "llsdserialize.h" +#include "llsingleton.h" #include "llstl.h" #include "lltimer.h" @@ -356,30 +357,31 @@ namespace typedef std::map<std::string, LLError::ELevel> LevelMap; - typedef std::vector<LLError::Recorder*> Recorders; + typedef std::vector<LLError::RecorderPtr> Recorders; typedef std::vector<LLError::CallSite*> CallSiteVector; - class Globals + class Globals : public LLSingleton<Globals> { public: + Globals(); + std::ostringstream messageStream; bool messageStreamInUse; void addCallSite(LLError::CallSite&); void invalidateCallSites(); - - static Globals& get(); - // return the one instance of the globals private: CallSiteVector callSites; - - Globals() - : messageStreamInUse(false) - { } - }; + Globals::Globals() + : messageStream(), + messageStreamInUse(false), + callSites() + { + } + void Globals::addCallSite(LLError::CallSite& site) { callSites.push_back(&site); @@ -396,25 +398,17 @@ namespace callSites.clear(); } - - Globals& Globals::get() - { - /* This pattern, of returning a reference to a static function - variable, is to ensure that this global is constructed before - it is used, no matter what the global initialization sequence - is. - See C++ FAQ Lite, sections 10.12 through 10.14 - */ - static Globals* globals = new Globals; - return *globals; - } } namespace LLError { - class Settings + class SettingsConfig : public LLRefCount { + friend class Settings; + public: + virtual ~SettingsConfig(); + bool mPrintLocation; LLError::ELevel mDefaultLevel; @@ -429,81 +423,86 @@ namespace LLError LLError::TimeFunction mTimeFunction; Recorders mRecorders; - Recorder* mFileRecorder; - Recorder* mFixedBufferRecorder; + RecorderPtr mFileRecorder; + RecorderPtr mFixedBufferRecorder; std::string mFileRecorderFileName; int mShouldLogCallCounter; - static Settings& get(); + private: + SettingsConfig(); + }; + + typedef LLPointer<SettingsConfig> SettingsConfigPtr; + + class Settings : public LLSingleton<Settings> + { + public: + Settings(); + + SettingsConfigPtr getSettingsConfig(); - static void reset(); - static Settings* saveAndReset(); - static void restore(Settings*); + void reset(); + SettingsStoragePtr saveAndReset(); + void restore(SettingsStoragePtr pSettingsStorage); private: - Settings() - : mPrintLocation(false), - mDefaultLevel(LLError::LEVEL_DEBUG), - mCrashFunction(), - mTimeFunction(NULL), - mFileRecorder(NULL), - mFixedBufferRecorder(NULL), - mShouldLogCallCounter(0) - { } - - ~Settings() - { - for_each(mRecorders.begin(), mRecorders.end(), DeletePointer()); - mRecorders.clear(); - } - - static Settings*& getPtr(); + SettingsConfigPtr mSettingsConfig; }; - Settings& Settings::get() + SettingsConfig::SettingsConfig() + : LLRefCount(), + mPrintLocation(false), + mDefaultLevel(LLError::LEVEL_DEBUG), + mFunctionLevelMap(), + mClassLevelMap(), + mFileLevelMap(), + mTagLevelMap(), + mUniqueLogMessages(), + mCrashFunction(NULL), + mTimeFunction(NULL), + mRecorders(), + mFileRecorder(), + mFixedBufferRecorder(), + mFileRecorderFileName(), + mShouldLogCallCounter(0) { - Settings* p = getPtr(); - if (!p) - { - reset(); - p = getPtr(); - } - return *p; } - - void Settings::reset() + + SettingsConfig::~SettingsConfig() { - Globals::get().invalidateCallSites(); - - Settings*& p = getPtr(); - delete p; - p = new Settings(); + mRecorders.clear(); + } + + Settings::Settings() + : LLSingleton<Settings>(), + mSettingsConfig(new SettingsConfig()) + { + } + + SettingsConfigPtr Settings::getSettingsConfig() + { + return mSettingsConfig; } - Settings* Settings::saveAndReset() + void Settings::reset() { - Globals::get().invalidateCallSites(); - - Settings*& p = getPtr(); - Settings* originalSettings = p; - p = new Settings(); - return originalSettings; + Globals::getInstance()->invalidateCallSites(); + mSettingsConfig = new SettingsConfig(); } - void Settings::restore(Settings* originalSettings) + SettingsStoragePtr Settings::saveAndReset() { - Globals::get().invalidateCallSites(); - - Settings*& p = getPtr(); - delete p; - p = originalSettings; + SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get()); + reset(); + return oldSettingsConfig; } - Settings*& Settings::getPtr() + void Settings::restore(SettingsStoragePtr pSettingsStorage) { - static Settings* currentSettings = NULL; - return currentSettings; + Globals::getInstance()->invalidateCallSites(); + SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get())); + mSettingsConfig = newSettingsConfig; } } @@ -604,7 +603,7 @@ namespace void commonInit(const std::string& dir, bool log_to_stderr = true) { - LLError::Settings::reset(); + LLError::Settings::getInstance()->reset(); LLError::setDefaultLevel(LLError::LEVEL_INFO); LLError::setFatalFunction(LLError::crashAndLoop); @@ -613,11 +612,13 @@ namespace // log_to_stderr is only false in the unit and integration tests to keep builds quieter if (log_to_stderr && shouldLogToStderr()) { - LLError::addRecorder(new RecordToStderr(stderrLogWantsTime())); + LLError::RecorderPtr recordToStdErr(new RecordToStderr(stderrLogWantsTime())); + LLError::addRecorder(recordToStdErr); } #if LL_WINDOWS - LLError::addRecorder(new RecordToWinDebug); + LLError::RecorderPtr recordToWinDebug(new RecordToWinDebug()); + LLError::addRecorder(recordToWinDebug); #endif LogControlFile& e = LogControlFile::fromDirectory(dir); @@ -645,7 +646,8 @@ namespace LLError } commonInit(dir); #if !LL_WINDOWS - addRecorder(new RecordToSyslog(identity)); + LLError::RecorderPtr recordToSyslog(new RecordToSyslog(identity)); + addRecorder(recordToSyslog); #endif } @@ -656,72 +658,67 @@ namespace LLError void setPrintLocation(bool print) { - Settings& s = Settings::get(); - s.mPrintLocation = print; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mPrintLocation = print; } void setFatalFunction(const FatalFunction& f) { - Settings& s = Settings::get(); - s.mCrashFunction = f; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mCrashFunction = f; } FatalFunction getFatalFunction() { - Settings& s = Settings::get(); - return s.mCrashFunction; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + return s->mCrashFunction; } void setTimeFunction(TimeFunction f) { - Settings& s = Settings::get(); - s.mTimeFunction = f; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mTimeFunction = f; } void setDefaultLevel(ELevel level) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); - g.invalidateCallSites(); - s.mDefaultLevel = level; + Globals::getInstance()->invalidateCallSites(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mDefaultLevel = level; } ELevel getDefaultLevel() { - Settings& s = Settings::get(); - return s.mDefaultLevel; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + return s->mDefaultLevel; } void setFunctionLevel(const std::string& function_name, ELevel level) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); - g.invalidateCallSites(); - s.mFunctionLevelMap[function_name] = level; + Globals::getInstance()->invalidateCallSites(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mFunctionLevelMap[function_name] = level; } void setClassLevel(const std::string& class_name, ELevel level) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); - g.invalidateCallSites(); - s.mClassLevelMap[class_name] = level; + Globals::getInstance()->invalidateCallSites(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mClassLevelMap[class_name] = level; } void setFileLevel(const std::string& file_name, ELevel level) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); - g.invalidateCallSites(); - s.mFileLevelMap[file_name] = level; + Globals::getInstance()->invalidateCallSites(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mFileLevelMap[file_name] = level; } void setTagLevel(const std::string& tag_name, ELevel level) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); - g.invalidateCallSites(); - s.mTagLevelMap[tag_name] = level; + Globals::getInstance()->invalidateCallSites(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mTagLevelMap[tag_name] = level; } LLError::ELevel decodeLevel(std::string name) @@ -765,15 +762,14 @@ namespace LLError { void configure(const LLSD& config) { - Globals& g = Globals::get(); - Settings& s = Settings::get(); + Globals::getInstance()->invalidateCallSites(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - g.invalidateCallSites(); - s.mFunctionLevelMap.clear(); - s.mClassLevelMap.clear(); - s.mFileLevelMap.clear(); - s.mTagLevelMap.clear(); - s.mUniqueLogMessages.clear(); + s->mFunctionLevelMap.clear(); + s->mClassLevelMap.clear(); + s->mFileLevelMap.clear(); + s->mTagLevelMap.clear(); + s->mUniqueLogMessages.clear(); setPrintLocation(config["print-location"]); setDefaultLevel(decodeLevel(config["default-level"])); @@ -786,10 +782,10 @@ namespace LLError ELevel level = decodeLevel(entry["level"]); - setLevels(s.mFunctionLevelMap, entry["functions"], level); - setLevels(s.mClassLevelMap, entry["classes"], level); - setLevels(s.mFileLevelMap, entry["files"], level); - setLevels(s.mTagLevelMap, entry["tags"], level); + setLevels(s->mFunctionLevelMap, entry["functions"], level); + setLevels(s->mClassLevelMap, entry["classes"], level); + setLevels(s->mFileLevelMap, entry["files"], level); + setLevels(s->mTagLevelMap, entry["tags"], level); } } } @@ -803,10 +799,12 @@ namespace LLError mWantsLevel(true), mWantsLocation(false), mWantsFunctionName(true) - {} + { + } Recorder::~Recorder() - { } + { + } bool Recorder::wantsTime() { @@ -837,25 +835,25 @@ namespace LLError return mWantsFunctionName; } - void addRecorder(Recorder* recorder) + void addRecorder(RecorderPtr recorder) { - if (recorder == NULL) + if (!recorder) { return; } - Settings& s = Settings::get(); - s.mRecorders.push_back(recorder); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mRecorders.push_back(recorder); } - void removeRecorder(Recorder* recorder) + void removeRecorder(RecorderPtr recorder) { - if (recorder == NULL) + if (!recorder) { return; } - Settings& s = Settings::get(); - s.mRecorders.erase(std::remove(s.mRecorders.begin(), s.mRecorders.end(), recorder), - s.mRecorders.end()); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder), + s->mRecorders.end()); } } @@ -863,51 +861,47 @@ namespace LLError { void logToFile(const std::string& file_name) { - LLError::Settings& s = LLError::Settings::get(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - removeRecorder(s.mFileRecorder); - delete s.mFileRecorder; - s.mFileRecorder = NULL; - s.mFileRecorderFileName.clear(); + removeRecorder(s->mFileRecorder); + s->mFileRecorder.reset(); + s->mFileRecorderFileName.clear(); if (file_name.empty()) { return; } - RecordToFile* f = new RecordToFile(file_name); - if (!f->okay()) + RecorderPtr recordToFile(new RecordToFile(file_name)); + if (boost::dynamic_pointer_cast<RecordToFile>(recordToFile)->okay()) { - delete f; - return; + s->mFileRecorderFileName = file_name; + s->mFileRecorder = recordToFile; + addRecorder(recordToFile); } - - s.mFileRecorderFileName = file_name; - s.mFileRecorder = f; - addRecorder(f); } void logToFixedBuffer(LLLineBuffer* fixedBuffer) { - LLError::Settings& s = LLError::Settings::get(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - removeRecorder(s.mFixedBufferRecorder); - delete s.mFixedBufferRecorder; - s.mFixedBufferRecorder = NULL; + removeRecorder(s->mFixedBufferRecorder); + s->mFixedBufferRecorder.reset(); if (!fixedBuffer) { return; } - s.mFixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer); - addRecorder(s.mFixedBufferRecorder); + RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer)); + s->mFixedBufferRecorder = recordToFixedBuffer; + addRecorder(recordToFixedBuffer); } std::string logFileName() { - LLError::Settings& s = LLError::Settings::get(); - return s.mFileRecorderFileName; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + return s->mFileRecorderFileName; } } @@ -916,24 +910,24 @@ namespace void writeToRecorders(const LLError::CallSite& site, const std::string& message, bool show_location = true, bool show_time = true, bool show_tags = true, bool show_level = true, bool show_function = true) { LLError::ELevel level = site.mLevel; - LLError::Settings& s = LLError::Settings::get(); + LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig(); - for (Recorders::const_iterator i = s.mRecorders.begin(); - i != s.mRecorders.end(); + for (Recorders::const_iterator i = s->mRecorders.begin(); + i != s->mRecorders.end(); ++i) { - LLError::Recorder* r = *i; + LLError::RecorderPtr r = *i; std::ostringstream message_stream; - if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s.mPrintLocation)) + if (show_location && (r->wantsLocation() || level == LLError::LEVEL_ERROR || s->mPrintLocation)) { message_stream << site.mLocationString << " "; } - if (show_time && r->wantsTime() && s.mTimeFunction != NULL) + if (show_time && r->wantsTime() && s->mTimeFunction != NULL) { - message_stream << s.mTimeFunction() << " "; + message_stream << s->mTimeFunction() << " "; } if (show_level && r->wantsLevel()) @@ -1060,10 +1054,9 @@ namespace LLError return false; } - Globals& g = Globals::get(); - Settings& s = Settings::get(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - s.mShouldLogCallCounter++; + s->mShouldLogCallCounter++; const std::string& class_name = className(site.mClassInfo); std::string function_name = functionName(site.mFunction); @@ -1077,21 +1070,21 @@ namespace LLError function_name = class_name + "::" + function_name; } - ELevel compareLevel = s.mDefaultLevel; + ELevel compareLevel = s->mDefaultLevel; // The most specific match found will be used as the log level, // since the computation short circuits. // So, in increasing order of importance: // Default < Tags < File < Class < Function - checkLevelMap(s.mFunctionLevelMap, function_name, compareLevel) - || checkLevelMap(s.mClassLevelMap, class_name, compareLevel) - || checkLevelMap(s.mFileLevelMap, abbreviateFile(site.mFile), compareLevel) + checkLevelMap(s->mFunctionLevelMap, function_name, compareLevel) + || checkLevelMap(s->mClassLevelMap, class_name, compareLevel) + || checkLevelMap(s->mFileLevelMap, abbreviateFile(site.mFile), compareLevel) || (site.mTagCount > 0 - ? checkLevelMap(s.mTagLevelMap, site.mTags, site.mTagCount, compareLevel) + ? checkLevelMap(s->mTagLevelMap, site.mTags, site.mTagCount, compareLevel) : false); site.mCached = true; - g.addCallSite(site); + Globals::getInstance()->addCallSite(site); return site.mShouldLog = site.mLevel >= compareLevel; } @@ -1101,12 +1094,12 @@ namespace LLError LogLock lock; if (lock.ok()) { - Globals& g = Globals::get(); + Globals* g = Globals::getInstance(); - if (!g.messageStreamInUse) + if (!g->messageStreamInUse) { - g.messageStreamInUse = true; - return &g.messageStream; + g->messageStreamInUse = true; + return &g->messageStream; } } @@ -1131,13 +1124,12 @@ namespace LLError message[127] = '\0' ; } - Globals& g = Globals::get(); - - if (out == &g.messageStream) + Globals* g = Globals::getInstance(); + if (out == &g->messageStream) { - g.messageStream.clear(); - g.messageStream.str(""); - g.messageStreamInUse = false; + g->messageStream.clear(); + g->messageStream.str(""); + g->messageStreamInUse = false; } else { @@ -1154,15 +1146,15 @@ namespace LLError return; } - Globals& g = Globals::get(); - Settings& s = Settings::get(); + Globals* g = Globals::getInstance(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); std::string message = out->str(); - if (out == &g.messageStream) + if (out == &g->messageStream) { - g.messageStream.clear(); - g.messageStream.str(""); - g.messageStreamInUse = false; + g->messageStream.clear(); + g->messageStream.str(""); + g->messageStreamInUse = false; } else { @@ -1178,8 +1170,8 @@ namespace LLError if (site.mPrintOnce) { - std::map<std::string, unsigned int>::iterator messageIter = s.mUniqueLogMessages.find(message); - if (messageIter != s.mUniqueLogMessages.end()) + std::map<std::string, unsigned int>::iterator messageIter = s->mUniqueLogMessages.find(message); + if (messageIter != s->mUniqueLogMessages.end()) { messageIter->second++; unsigned int num_messages = messageIter->second; @@ -1195,7 +1187,7 @@ namespace LLError else { message_stream << "ONCE: "; - s.mUniqueLogMessages[message] = 1; + s->mUniqueLogMessages[message] = 1; } } @@ -1203,23 +1195,23 @@ namespace LLError writeToRecorders(site, message_stream.str()); - if (site.mLevel == LEVEL_ERROR && s.mCrashFunction) + if (site.mLevel == LEVEL_ERROR && s->mCrashFunction) { - s.mCrashFunction(message_stream.str()); + s->mCrashFunction(message_stream.str()); } } } namespace LLError { - Settings* saveAndResetSettings() + SettingsStoragePtr saveAndResetSettings() { - return Settings::saveAndReset(); + return Settings::getInstance()->saveAndReset(); } - void restoreSettings(Settings* s) + void restoreSettings(SettingsStoragePtr pSettingsStorage) { - return Settings::restore(s); + return Settings::getInstance()->restore(pSettingsStorage); } std::string removePrefix(std::string& s, const std::string& p) @@ -1265,8 +1257,8 @@ namespace LLError int shouldLogCallCount() { - Settings& s = Settings::get(); - return s.mShouldLogCallCounter; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + return s->mShouldLogCallCounter; } #if LL_WINDOWS @@ -1375,15 +1367,9 @@ namespace LLError #endif //static - void LLCallStacks::push(const char* function, const int line) + void LLCallStacks::allocateStackBuffer() { - CallStacksLogLock lock; - if (!lock.ok()) - { - return; - } - - if(!sBuffer) + if(sBuffer == NULL) { sBuffer = new char*[512] ; sBuffer[0] = new char[512 * 128] ; @@ -1393,6 +1379,31 @@ namespace LLError } sIndex = 0 ; } + } + + void LLCallStacks::freeStackBuffer() + { + if(sBuffer != NULL) + { + delete [] sBuffer[0] ; + delete [] sBuffer ; + sBuffer = NULL ; + } + } + + //static + void LLCallStacks::push(const char* function, const int line) + { + CallStacksLogLock lock; + if (!lock.ok()) + { + return; + } + + if(sBuffer == NULL) + { + allocateStackBuffer(); + } if(sIndex > 511) { @@ -1424,15 +1435,9 @@ namespace LLError return; } - if(!sBuffer) + if(sBuffer == NULL) { - sBuffer = new char*[512] ; - sBuffer[0] = new char[512 * 128] ; - for(S32 i = 1 ; i < 512 ; i++) - { - sBuffer[i] = sBuffer[i-1] + 128 ; - } - sIndex = 0 ; + allocateStackBuffer(); } if(sIndex > 511) @@ -1463,11 +1468,9 @@ namespace LLError LL_INFOS() << " *************** END OF LL CALL STACKS *************** " << LL_ENDL; } - if(sBuffer) + if(sBuffer != NULL) { - delete[] sBuffer[0] ; - delete[] sBuffer ; - sBuffer = NULL ; + freeStackBuffer(); } } @@ -1477,5 +1480,10 @@ namespace LLError sIndex = 0 ; } + //static + void LLCallStacks::cleanup() + { + freeStackBuffer(); + } } diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index bc80e64423..63040e1772 100755 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -261,6 +261,9 @@ namespace LLError private: static char** sBuffer ; static S32 sIndex ; + + static void allocateStackBuffer(); + static void freeStackBuffer(); public: static void push(const char* function, const int line) ; @@ -268,6 +271,7 @@ namespace LLError static void print() ; static void clear() ; static void end(std::ostringstream* _out) ; + static void cleanup(); }; } diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index aab695094c..56ac52e5de 100755 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -29,7 +29,10 @@ #define LL_LLERRORCONTROL_H #include "llerror.h" +#include "llpointer.h" +#include "llrefcount.h" #include "boost/function.hpp" +#include "boost/shared_ptr.hpp" #include <string> class LLSD; @@ -156,16 +159,14 @@ namespace LLError mWantsFunctionName; }; + typedef boost::shared_ptr<Recorder> RecorderPtr; + /** - * @NOTE: addRecorder() conveys ownership to the underlying Settings - * object -- when destroyed, it will @em delete the passed Recorder*! - */ - LL_COMMON_API void addRecorder(Recorder*); - /** - * @NOTE: removeRecorder() reclaims ownership of the Recorder*: its - * lifespan becomes the caller's problem. + * @NOTE: addRecorder() and removeRecorder() uses the boost::shared_ptr to allow for shared ownership + * while still ensuring that the allocated memory is eventually freed */ - LL_COMMON_API void removeRecorder(Recorder*); + LL_COMMON_API void addRecorder(RecorderPtr); + LL_COMMON_API void removeRecorder(RecorderPtr); // each error message is passed to each recorder via recordMessage() LL_COMMON_API void logToFile(const std::string& filename); @@ -182,9 +183,9 @@ namespace LLError Utilities for use by the unit tests of LLError itself. */ - class Settings; - LL_COMMON_API Settings* saveAndResetSettings(); - LL_COMMON_API void restoreSettings(Settings *); + typedef LLPointer<LLRefCount> SettingsStoragePtr; + LL_COMMON_API SettingsStoragePtr saveAndResetSettings(); + LL_COMMON_API void restoreSettings(SettingsStoragePtr pSettingsStorage); LL_COMMON_API std::string abbreviateFile(const std::string& filePath); LL_COMMON_API int shouldLogCallCount(); diff --git a/indra/llcommon/llhttpstatuscodes.h b/indra/llcommon/llhttpstatuscodes.h deleted file mode 100755 index 0173461dad..0000000000 --- a/indra/llcommon/llhttpstatuscodes.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @file llhttpstatuscodes.h - * @brief Constants for HTTP status codes - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_HTTP_STATUS_CODES_H -#define LL_HTTP_STATUS_CODES_H - -#include "stdtypes.h" - -// Standard errors from HTTP spec: -// http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1 -const S32 HTTP_CONTINUE = 100; -const S32 HTTP_SWITCHING_PROTOCOLS = 101; - -// Success -const S32 HTTP_OK = 200; -const S32 HTTP_CREATED = 201; -const S32 HTTP_ACCEPTED = 202; -const S32 HTTP_NON_AUTHORITATIVE_INFORMATION = 203; -const S32 HTTP_NO_CONTENT = 204; -const S32 HTTP_RESET_CONTENT = 205; -const S32 HTTP_PARTIAL_CONTENT = 206; - -// Redirection -const S32 HTTP_MULTIPLE_CHOICES = 300; -const S32 HTTP_MOVED_PERMANENTLY = 301; -const S32 HTTP_FOUND = 302; -const S32 HTTP_SEE_OTHER = 303; -const S32 HTTP_NOT_MODIFIED = 304; -const S32 HTTP_USE_PROXY = 305; -const S32 HTTP_TEMPORARY_REDIRECT = 307; - -// Client Error -const S32 HTTP_BAD_REQUEST = 400; -const S32 HTTP_UNAUTHORIZED = 401; -const S32 HTTP_PAYMENT_REQUIRED = 402; -const S32 HTTP_FORBIDDEN = 403; -const S32 HTTP_NOT_FOUND = 404; -const S32 HTTP_METHOD_NOT_ALLOWED = 405; -const S32 HTTP_NOT_ACCEPTABLE = 406; -const S32 HTTP_PROXY_AUTHENTICATION_REQUIRED = 407; -const S32 HTTP_REQUEST_TIME_OUT = 408; -const S32 HTTP_CONFLICT = 409; -const S32 HTTP_GONE = 410; -const S32 HTTP_LENGTH_REQUIRED = 411; -const S32 HTTP_PRECONDITION_FAILED = 412; -const S32 HTTP_REQUEST_ENTITY_TOO_LARGE = 413; -const S32 HTTP_REQUEST_URI_TOO_LARGE = 414; -const S32 HTTP_UNSUPPORTED_MEDIA_TYPE = 415; -const S32 HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416; -const S32 HTTP_EXPECTATION_FAILED = 417; - -// Server Error -const S32 HTTP_INTERNAL_SERVER_ERROR = 500; -const S32 HTTP_NOT_IMPLEMENTED = 501; -const S32 HTTP_BAD_GATEWAY = 502; -const S32 HTTP_SERVICE_UNAVAILABLE = 503; -const S32 HTTP_GATEWAY_TIME_OUT = 504; -const S32 HTTP_VERSION_NOT_SUPPORTED = 505; - -// We combine internal process errors with status codes -// These status codes should not be sent over the wire -// and indicate something went wrong internally. -// If you get these they are not normal. -const S32 HTTP_INTERNAL_ERROR = 499; - -#endif diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 2532566319..7aa87fcd0e 100755 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -31,6 +31,7 @@ #include <vector> #include <list> #include <boost/function.hpp> +#include <boost/shared_ptr.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_enum.hpp> #include <boost/unordered_map.hpp> @@ -629,7 +630,7 @@ namespace LLInitParam UserData* mUserData; }; - typedef ParamDescriptor* ParamDescriptorPtr; + typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr; // each derived Block class keeps a static data structure maintaining offsets to various params class LL_COMMON_API BlockDescriptor diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h index c9ebc70d19..9a6453ea48 100755 --- a/indra/llcommon/llpointer.h +++ b/indra/llcommon/llpointer.h @@ -166,6 +166,132 @@ protected: Type* mPointer; }; +template <class Type> class LLConstPointer +{ +public: + LLConstPointer() : + mPointer(NULL) + { + } + + LLConstPointer(const Type* ptr) : + mPointer(ptr) + { + ref(); + } + + LLConstPointer(const LLConstPointer<Type>& ptr) : + mPointer(ptr.mPointer) + { + ref(); + } + + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template<typename Subclass> + LLConstPointer(const LLConstPointer<Subclass>& ptr) : + mPointer(ptr.get()) + { + ref(); + } + + ~LLConstPointer() + { + unref(); + } + + const Type* get() const { return mPointer; } + const Type* operator->() const { return mPointer; } + const Type& operator*() const { return *mPointer; } + + operator BOOL() const { return (mPointer != NULL); } + operator bool() const { return (mPointer != NULL); } + bool operator!() const { return (mPointer == NULL); } + bool isNull() const { return (mPointer == NULL); } + bool notNull() const { return (mPointer != NULL); } + + operator const Type*() const { return mPointer; } + bool operator !=(const Type* ptr) const { return (mPointer != ptr); } + bool operator ==(const Type* ptr) const { return (mPointer == ptr); } + bool operator ==(const LLConstPointer<Type>& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLConstPointer<Type>& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLConstPointer<Type>& ptr) const { return (mPointer > ptr.mPointer); } + + LLConstPointer<Type>& operator =(const Type* ptr) + { + if( mPointer != ptr ) + { + unref(); + mPointer = ptr; + ref(); + } + + return *this; + } + + LLConstPointer<Type>& operator =(const LLConstPointer<Type>& ptr) + { + if( mPointer != ptr.mPointer ) + { + unref(); + mPointer = ptr.mPointer; + ref(); + } + return *this; + } + + // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template<typename Subclass> + LLConstPointer<Type>& operator =(const LLConstPointer<Subclass>& ptr) + { + if( mPointer != ptr.get() ) + { + unref(); + mPointer = ptr.get(); + ref(); + } + return *this; + } + + // Just exchange the pointers, which will not change the reference counts. + static void swap(LLConstPointer<Type>& a, LLConstPointer<Type>& b) + { + const Type* temp = a.mPointer; + a.mPointer = b.mPointer; + b.mPointer = temp; + } + +protected: +#ifdef LL_LIBRARY_INCLUDE + void ref(); + void unref(); +#else + void ref() + { + if (mPointer) + { + mPointer->ref(); + } + } + + void unref() + { + if (mPointer) + { + const Type *tempp = mPointer; + mPointer = NULL; + tempp->unref(); + if (mPointer != NULL) + { + LL_WARNS() << "Unreference did assignment to non-NULL because of destructor" << LL_ENDL; + unref(); + } + } + } +#endif +protected: + const Type* mPointer; +}; + template<typename Type> class LLCopyOnWritePointer : public LLPointer<Type> { diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index f962485284..d8bbb3a74f 100755 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -126,7 +126,9 @@ public: virtual UUID asUUID() const { return LLUUID(); } virtual Date asDate() const { return LLDate(); } virtual URI asURI() const { return LLURI(); } - virtual Binary asBinary() const { return std::vector<U8>(); } + virtual const Binary& asBinary() const { static const std::vector<U8> empty; return empty; } + + virtual const String& asStringRef() const { static const std::string empty; return empty; } virtual bool has(const String&) const { return false; } virtual LLSD get(const String&) const { return LLSD(); } @@ -270,6 +272,7 @@ namespace virtual LLSD::Date asDate() const { return LLDate(mValue); } virtual LLSD::URI asURI() const { return LLURI(mValue); } virtual int size() const { return mValue.size(); } + virtual const LLSD::String& asStringRef() const { return mValue; } }; LLSD::Integer ImplString::asInteger() const @@ -348,7 +351,7 @@ namespace public: ImplBinary(const LLSD::Binary& v) : Base(v) { } - virtual LLSD::Binary asBinary() const{ return mValue; } + virtual const LLSD::Binary& asBinary() const{ return mValue; } }; @@ -840,7 +843,9 @@ LLSD::String LLSD::asString() const { return safe(impl).asString(); } LLSD::UUID LLSD::asUUID() const { return safe(impl).asUUID(); } LLSD::Date LLSD::asDate() const { return safe(impl).asDate(); } LLSD::URI LLSD::asURI() const { return safe(impl).asURI(); } -LLSD::Binary LLSD::asBinary() const { return safe(impl).asBinary(); } +const LLSD::Binary& LLSD::asBinary() const { return safe(impl).asBinary(); } + +const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); } // const char * helpers LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); } diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h index deb87d7497..7b9b1285f5 100755 --- a/indra/llcommon/llsd.h +++ b/indra/llcommon/llsd.h @@ -249,7 +249,10 @@ public: UUID asUUID() const; Date asDate() const; URI asURI() const; - Binary asBinary() const; + const Binary& asBinary() const; + + // asStringRef on any non-string type will return a ref to an empty string. + const String& asStringRef() const; operator Boolean() const { return asBoolean(); } operator Integer() const { return asInteger(); } diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 04d7a6ed56..d49ff0feb5 100755 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -34,7 +34,7 @@ #include <iostream> #include "apr_base64.h" -#ifdef LL_STANDALONE +#ifdef LL_USESYSTEMLIBS # include <zlib.h> #else # include "zlib/zlib.h" // for davep's dirty little zip functions @@ -873,7 +873,7 @@ S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const { /** * Undefined: '!'<br> - * Boolean: 't' for true 'f' for false<br> + * Boolean: '1' for true '0' for false<br> * Integer: 'i' + 4 bytes network byte order<br> * Real: 'r' + 8 bytes IEEE double<br> * UUID: 'u' + 16 byte unsigned integer<br> @@ -1261,12 +1261,37 @@ std::string LLSDNotationFormatter::escapeString(const std::string& in) // virtual S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const { + S32 rv = format_impl(data, ostr, options, 0); + return rv; +} + +S32 LLSDNotationFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const +{ S32 format_count = 1; + std::string pre; + std::string post; + + if (options & LLSDFormatter::OPTIONS_PRETTY) + { + for (U32 i = 0; i < level; i++) + { + pre += " "; + } + post = "\n"; + } + switch(data.type()) { case LLSD::TypeMap: { + if (0 != level) ostr << post << pre; ostr << "{"; + std::string inner_pre; + if (options & LLSDFormatter::OPTIONS_PRETTY) + { + inner_pre = pre + " "; + } + bool need_comma = false; LLSD::map_const_iterator iter = data.beginMap(); LLSD::map_const_iterator end = data.endMap(); @@ -1274,18 +1299,18 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti { if(need_comma) ostr << ","; need_comma = true; - ostr << '\''; + ostr << post << inner_pre << '\''; serialize_string((*iter).first, ostr); ostr << "':"; - format_count += format((*iter).second, ostr); + format_count += format_impl((*iter).second, ostr, options, level + 2); } - ostr << "}"; + ostr << post << pre << "}"; break; } case LLSD::TypeArray: { - ostr << "["; + ostr << post << pre << "["; bool need_comma = false; LLSD::array_const_iterator iter = data.beginArray(); LLSD::array_const_iterator end = data.endArray(); @@ -1293,7 +1318,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti { if(need_comma) ostr << ","; need_comma = true; - format_count += format(*iter, ostr); + format_count += format_impl(*iter, ostr, options, level + 1); } ostr << "]"; break; @@ -1343,7 +1368,7 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti case LLSD::TypeString: ostr << '\''; - serialize_string(data.asString(), ostr); + serialize_string(data.asStringRef(), ostr); ostr << '\''; break; @@ -1360,9 +1385,26 @@ S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 opti case LLSD::TypeBinary: { // *FIX: memory inefficient. - std::vector<U8> buffer = data.asBinary(); + const std::vector<U8>& buffer = data.asBinary(); ostr << "b(" << buffer.size() << ")\""; - if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); + if(buffer.size()) + { + if (options & LLSDFormatter::OPTIONS_PRETTY_BINARY) + { + std::ios_base::fmtflags old_flags = ostr.flags(); + ostr.setf( std::ios::hex, std::ios::basefield ); + ostr << "0x"; + for (int i = 0; i < buffer.size(); i++) + { + ostr << (int) buffer[i]; + } + ostr.flags(old_flags); + } + else + { + ostr.write((const char*)&buffer[0], buffer.size()); + } + } ostr << "\""; break; } @@ -1460,7 +1502,7 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option case LLSD::TypeString: ostr.put('s'); - formatString(data.asString(), ostr); + formatString(data.asStringRef(), ostr); break; case LLSD::TypeDate: @@ -1478,9 +1520,8 @@ S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 option case LLSD::TypeBinary: { - // *FIX: memory inefficient. ostr.put('b'); - std::vector<U8> buffer = data.asBinary(); + const std::vector<U8>& buffer = data.asBinary(); U32 size_nbo = htonl(buffer.size()); ostr.write((const char*)(&size_nbo), sizeof(U32)); if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index e7a5507385..23a0c8cfb1 100755 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -416,7 +416,8 @@ public: typedef enum e_formatter_options_type { OPTIONS_NONE = 0, - OPTIONS_PRETTY = 1 + OPTIONS_PRETTY = 1, + OPTIONS_PRETTY_BINARY = 2 } EFormatterOptions; /** @@ -507,6 +508,17 @@ public: * @return Returns The number of LLSD objects fomatted out */ virtual S32 format(const LLSD& data, std::ostream& ostr, U32 options = LLSDFormatter::OPTIONS_NONE) const; + +protected: + + /** + * @brief Implementation to format the data. This is called recursively. + * + * @param data The data to write. + * @param ostr The destination stream for the data. + * @return Returns The number of LLSD objects fomatted out + */ + S32 format_impl(const LLSD& data, std::ostream& ostr, U32 options, U32 level) const; }; @@ -634,7 +646,7 @@ protected: * </code> * * *NOTE - formerly this class inherited from its template parameter Formatter, - * but all insnatiations passed in LLRefCount subclasses. This conflicted with + * but all instantiations passed in LLRefCount subclasses. This conflicted with * the auto allocation intended for this class template (demonstrated in the * example above). -brad */ @@ -720,6 +732,18 @@ public: LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter; return f->format(sd, str, LLSDFormatter::OPTIONS_NONE); } + static S32 toPrettyNotation(const LLSD& sd, std::ostream& str) + { + LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter; + return f->format(sd, str, LLSDFormatter::OPTIONS_PRETTY); + } + static S32 toPrettyBinaryNotation(const LLSD& sd, std::ostream& str) + { + LLPointer<LLSDNotationFormatter> f = new LLSDNotationFormatter; + return f->format(sd, str, + LLSDFormatter::OPTIONS_PRETTY | + LLSDFormatter::OPTIONS_PRETTY_BINARY); + } static S32 fromNotation(LLSD& sd, std::istream& str, S32 max_bytes) { LLPointer<LLSDNotationParser> p = new LLSDNotationParser; diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 4e2af0e589..8d72a1c329 100755 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -35,7 +35,7 @@ extern "C" { -#ifdef LL_STANDALONE +#ifdef LL_USESYSTEMLIBS # include <expat.h> #else # include "expat/expat.h" @@ -168,8 +168,8 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti break; case LLSD::TypeString: - if(data.asString().empty()) ostr << pre << "<string />" << post; - else ostr << pre << "<string>" << escapeString(data.asString()) <<"</string>" << post; + if(data.asStringRef().empty()) ostr << pre << "<string />" << post; + else ostr << pre << "<string>" << escapeString(data.asStringRef()) <<"</string>" << post; break; case LLSD::TypeDate: @@ -182,7 +182,7 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti case LLSD::TypeBinary: { - LLSD::Binary buffer = data.asBinary(); + const LLSD::Binary& buffer = data.asBinary(); if(buffer.empty()) { ostr << pre << "<binary />" << post; @@ -375,13 +375,10 @@ S32 LLSDXMLParser::Impl::parse(std::istream& input, LLSD& data) { break; } + count = get_till_eol(input, (char *)buffer, BUFFER_SIZE); + if (!count) { - - count = get_till_eol(input, (char *)buffer, BUFFER_SIZE); - if (!count) - { - break; - } + break; } status = XML_ParseBuffer(mParser, count, false); diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index 803417d368..562fd26658 100755 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -182,7 +182,7 @@ char* ll_pretty_print_sd_ptr(const LLSD* sd) char* ll_pretty_print_sd(const LLSD& sd) { - const U32 bufferSize = 10 * 1024; + const U32 bufferSize = 100 * 1024; static char buffer[bufferSize]; std::ostringstream stream; //stream.rdbuf()->pubsetbuf(buffer, bufferSize); diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 07fe259e47..06e118aa44 100755 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -33,7 +33,7 @@ #include "llsys.h" #include <iostream> -#ifdef LL_STANDALONE +#ifdef LL_USESYSTEMLIBS # include <zlib.h> #else # include "zlib/zlib.h" diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index 0699dcda83..dd8660a3c8 100755 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -132,10 +132,14 @@ public: }; typedef std::vector<LLUUID> uuid_vec_t; - - -// Helper structure for ordering lluuids in stl containers. -// eg: std::map<LLUUID, LLWidget*, lluuid_less> widget_map; +typedef std::set<LLUUID> uuid_set_t; + +// Helper structure for ordering lluuids in stl containers. eg: +// std::map<LLUUID, LLWidget*, lluuid_less> widget_map; +// +// (isn't this the default behavior anyway? I think we could +// everywhere replace these with uuid_set_t, but someone should +// verify.) struct lluuid_less { bool operator()(const LLUUID& lhs, const LLUUID& rhs) const @@ -145,7 +149,6 @@ struct lluuid_less }; typedef std::set<LLUUID, lluuid_less> uuid_list_t; - /* * Sub-classes for keeping transaction IDs and asset IDs * straight. diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index b28c5ba4b3..a5aaff10c5 100755 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -56,9 +56,9 @@ namespace tut { public: TestRecorder() { mWantsTime = false; } - ~TestRecorder() { LLError::removeRecorder(this); } + virtual ~TestRecorder() { } - void recordMessage(LLError::ELevel level, + virtual void recordMessage(LLError::ELevel level, const std::string& message) { mMessages.push_back(message); @@ -85,15 +85,11 @@ namespace tut struct ErrorTestData { - // addRecorder() expects to be able to later delete the passed - // Recorder*. Even though removeRecorder() reclaims ownership, passing - // a pointer to a data member rather than a heap Recorder subclass - // instance would just be Wrong. - TestRecorder* mRecorder; - LLError::Settings* mPriorErrorSettings; + LLError::RecorderPtr mRecorder; + LLError::SettingsStoragePtr mPriorErrorSettings; ErrorTestData(): - mRecorder(new TestRecorder) + mRecorder(new TestRecorder()) { fatalWasCalled = false; @@ -106,13 +102,32 @@ namespace tut ~ErrorTestData() { LLError::removeRecorder(mRecorder); - delete mRecorder; LLError::restoreSettings(mPriorErrorSettings); } + int countMessages() + { + return boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->countMessages(); + } + + void clearMessages() + { + boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->clearMessages(); + } + + void setWantsTime(bool t) + { + boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->setWantsTime(t); + } + + std::string message(int n) + { + return boost::dynamic_pointer_cast<TestRecorder>(mRecorder)->message(n); + } + void ensure_message_count(int expectedCount) { - ensure_equals("message count", mRecorder->countMessages(), expectedCount); + ensure_equals("message count", countMessages(), expectedCount); } void ensure_message_contains(int n, const std::string& expectedText) @@ -120,7 +135,7 @@ namespace tut std::ostringstream test_name; test_name << "testing message " << n; - ensure_contains(test_name.str(), mRecorder->message(n), expectedText); + ensure_contains(test_name.str(), message(n), expectedText); } void ensure_message_does_not_contain(int n, const std::string& expectedText) @@ -128,7 +143,7 @@ namespace tut std::ostringstream test_name; test_name << "testing message " << n; - ensure_does_not_contain(test_name.str(), mRecorder->message(n), expectedText); + ensure_does_not_contain(test_name.str(), message(n), expectedText); } }; @@ -385,15 +400,15 @@ namespace } typedef std::string (*LogFromFunction)(bool); - void testLogName(tut::TestRecorder* recorder, LogFromFunction f, + void testLogName(LLError::RecorderPtr recorder, LogFromFunction f, const std::string& class_name = "") { - recorder->clearMessages(); + boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->clearMessages(); std::string name = f(false); f(true); - std::string messageWithoutName = recorder->message(0); - std::string messageWithName = recorder->message(1); + std::string messageWithoutName = boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(0); + std::string messageWithName = boost::dynamic_pointer_cast<tut::TestRecorder>(recorder)->message(1); ensure_has(name + " logged without name", messageWithoutName, name); @@ -528,12 +543,12 @@ namespace tut { LLError::setTimeFunction(roswell); - mRecorder->setWantsTime(false); + setWantsTime(false); ufoSighting(); ensure_message_contains(0, "ufo"); ensure_message_does_not_contain(0, roswell()); - mRecorder->setWantsTime(true); + setWantsTime(true); ufoSighting(); ensure_message_contains(1, "ufo"); ensure_message_contains(1, roswell()); @@ -545,13 +560,13 @@ namespace tut { LLError::setPrintLocation(true); LLError::setTimeFunction(roswell); - mRecorder->setWantsTime(true); + setWantsTime(true); std::string location, function; writeReturningLocationAndFunction(location, function); ensure_equals("order is location time type function message", - mRecorder->message(0), + message(0), location + roswell() + " INFO: " + function + ": apple"); } @@ -559,19 +574,19 @@ namespace tut // multiple recorders void ErrorTestObject::test<11>() { - TestRecorder* altRecorder(new TestRecorder); + LLError::RecorderPtr altRecorder(new TestRecorder()); LLError::addRecorder(altRecorder); LL_INFOS() << "boo" << LL_ENDL; ensure_message_contains(0, "boo"); - ensure_equals("alt recorder count", altRecorder->countMessages(), 1); - ensure_contains("alt recorder message 0", altRecorder->message(0), "boo"); + ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 1); + ensure_contains("alt recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(0), "boo"); LLError::setTimeFunction(roswell); - TestRecorder* anotherRecorder(new TestRecorder); - anotherRecorder->setWantsTime(true); + LLError::RecorderPtr anotherRecorder(new TestRecorder()); + boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->setWantsTime(true); LLError::addRecorder(anotherRecorder); LL_INFOS() << "baz" << LL_ENDL; @@ -579,10 +594,13 @@ namespace tut std::string when = roswell(); ensure_message_does_not_contain(1, when); - ensure_equals("alt recorder count", altRecorder->countMessages(), 2); - ensure_does_not_contain("alt recorder message 1", altRecorder->message(1), when); - ensure_equals("another recorder count", anotherRecorder->countMessages(), 1); - ensure_contains("another recorder message 0", anotherRecorder->message(0), when); + ensure_equals("alt recorder count", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->countMessages(), 2); + ensure_does_not_contain("alt recorder message 1", boost::dynamic_pointer_cast<TestRecorder>(altRecorder)->message(1), when); + ensure_equals("another recorder count", boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->countMessages(), 1); + ensure_contains("another recorder message 0", boost::dynamic_pointer_cast<TestRecorder>(anotherRecorder)->message(0), when); + + LLError::removeRecorder(altRecorder); + LLError::removeRecorder(anotherRecorder); } } diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp index 3e4ca548e5..2a4ed44a67 100755 --- a/indra/llcommon/tests/stringize_test.cpp +++ b/indra/llcommon/tests/stringize_test.cpp @@ -95,7 +95,7 @@ namespace tut ensure_equals(stringize(f), "3.14159"); ensure_equals(stringize(d), "3.14159"); ensure_equals(stringize(abc), "abc def"); - ensure_equals(stringize(def), "def ghi"); //Will generate llwarns due to narrowing. + ensure_equals(stringize(def), "def ghi"); //Will generate LL_WARNS() due to narrowing. ensure_equals(stringize(llsd), "{'abc':'abc def','d':r3.14159,'i':i34}"); } diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index 3137bd8fea..785197ba11 100755 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -38,6 +38,7 @@ #include "stringize.h" #include <boost/bind.hpp> #include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> #include <list> #include <string> #include <stdexcept> @@ -81,72 +82,29 @@ struct WrapLLErrs } std::string error; - LLError::Settings* mPriorErrorSettings; + LLError::SettingsStoragePtr mPriorErrorSettings; LLError::FatalFunction mPriorFatal; }; /** - * LLError::addRecorder() accepts ownership of the passed Recorder* -- it - * expects to be able to delete it later. CaptureLog isa Recorder whose - * pointer we want to be able to pass without any ownership implications. - * For such cases, instantiate a new RecorderProxy(yourRecorder) and pass - * that. Your heap RecorderProxy might later be deleted, but not yourRecorder. - */ -class RecorderProxy: public LLError::Recorder -{ -public: - RecorderProxy(LLError::Recorder* recorder): - mRecorder(recorder) - {} - - virtual void recordMessage(LLError::ELevel level, const std::string& message) - { - mRecorder->recordMessage(level, message); - } - - virtual bool wantsTime() - { - return mRecorder->wantsTime(); - } - -private: - LLError::Recorder* mRecorder; -}; - -/** * Capture log messages. This is adapted (simplified) from the one in * llerror_test.cpp. */ -class CaptureLog : public LLError::Recorder, public boost::noncopyable +class CaptureLogRecorder : public LLError::Recorder, public boost::noncopyable { public: - CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG): - // Mostly what we're trying to accomplish by saving and resetting - // LLError::Settings is to bypass the default RecordToStderr and - // RecordToWinDebug Recorders. As these are visible only inside - // llerror.cpp, we can't just call LLError::removeRecorder() with - // each. For certain tests we need to produce, capture and examine - // DEBUG log messages -- but we don't want to spam the user's console - // with that output. If it turns out that saveAndResetSettings() has - // some bad effect, give up and just let the DEBUG level log messages - // display. - mOldSettings(LLError::saveAndResetSettings()), - mProxy(new RecorderProxy(this)) + CaptureLogRecorder() + : LLError::Recorder(), + boost::noncopyable(), + mMessages() { - LLError::setFatalFunction(wouldHaveCrashed); - LLError::setDefaultLevel(level); - LLError::addRecorder(mProxy); } - ~CaptureLog() + virtual ~CaptureLogRecorder() { - LLError::removeRecorder(mProxy); - delete mProxy; - LLError::restoreSettings(mOldSettings); } - void recordMessage(LLError::ELevel level, - const std::string& message) + virtual void recordMessage(LLError::ELevel level, const std::string& message) { mMessages.push_back(message); } @@ -154,7 +112,7 @@ public: /// Don't assume the message we want is necessarily the LAST log message /// emitted by the underlying code; search backwards through all messages /// for the sought string. - std::string messageWith(const std::string& search, bool required=true) + std::string messageWith(const std::string& search, bool required) { for (MessageList::const_reverse_iterator rmi(mMessages.rbegin()), rmend(mMessages.rend()); rmi != rmend; ++rmi) @@ -187,14 +145,63 @@ public: return out; } +private: typedef std::list<std::string> MessageList; MessageList mMessages; - LLError::Settings* mOldSettings; - LLError::Recorder* mProxy; +}; + +/** + * Capture log messages. This is adapted (simplified) from the one in + * llerror_test.cpp. + */ +class CaptureLog : public boost::noncopyable +{ +public: + CaptureLog(LLError::ELevel level=LLError::LEVEL_DEBUG) + // Mostly what we're trying to accomplish by saving and resetting + // LLError::Settings is to bypass the default RecordToStderr and + // RecordToWinDebug Recorders. As these are visible only inside + // llerror.cpp, we can't just call LLError::removeRecorder() with + // each. For certain tests we need to produce, capture and examine + // DEBUG log messages -- but we don't want to spam the user's console + // with that output. If it turns out that saveAndResetSettings() has + // some bad effect, give up and just let the DEBUG level log messages + // display. + : boost::noncopyable(), + mOldSettings(LLError::saveAndResetSettings()), + mRecorder(new CaptureLogRecorder()) + { + LLError::setFatalFunction(wouldHaveCrashed); + LLError::setDefaultLevel(level); + LLError::addRecorder(mRecorder); + } + + ~CaptureLog() + { + LLError::removeRecorder(mRecorder); + LLError::restoreSettings(mOldSettings); + } + + /// Don't assume the message we want is necessarily the LAST log message + /// emitted by the underlying code; search backwards through all messages + /// for the sought string. + std::string messageWith(const std::string& search, bool required=true) + { + return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->messageWith(search, required); + } + + std::ostream& streamto(std::ostream& out) const + { + return boost::dynamic_pointer_cast<CaptureLogRecorder>(mRecorder)->streamto(out); + } + +private: + LLError::SettingsStoragePtr mOldSettings; + LLError::RecorderPtr mRecorder; }; inline -std::ostream& operator<<(std::ostream& out, const CaptureLog& log) +std::ostream& operator<<(std::ostream& out, const CaptureLogRecorder& log) { return log.streamto(out); } |