From 487ca1bad37883be0325b564ab557a8f77575388 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 14 May 2014 17:50:59 -0400 Subject: v-r -> s-e merge WIP --- indra/llcommon/tests/stringize_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/tests') 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}"); } -- cgit v1.3 From 34b2f2d1f841f7b7f93386d66be6943910cd055b Mon Sep 17 00:00:00 2001 From: Stinson Linden Date: Fri, 16 May 2014 22:44:25 +0100 Subject: MAINT-4009: First pass refactoring to eliminate memory related to error reporting that is not properly cleaned up. --- indra/llcommon/llerror.cpp | 54 ++++++++-------- indra/llcommon/llerrorcontrol.h | 15 +++-- indra/llcommon/tests/llerror_test.cpp | 76 ++++++++++++++--------- indra/llcommon/tests/wrapllerrs.h | 113 ++++++++++++++++++---------------- indra/newview/llviewerwindow.cpp | 25 ++++++-- indra/test/test.cpp | 62 ++++++++++++++----- 6 files changed, 205 insertions(+), 140 deletions(-) (limited to 'indra/llcommon/tests') diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 4f721fabdf..09a2d38e1a 100755 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -357,7 +357,7 @@ namespace typedef std::map LevelMap; - typedef std::vector Recorders; + typedef std::vector Recorders; typedef std::vector CallSiteVector; class Globals : public LLSingleton @@ -419,8 +419,8 @@ namespace LLError LLError::TimeFunction mTimeFunction; Recorders mRecorders; - Recorder* mFileRecorder; - Recorder* mFixedBufferRecorder; + RecorderPtr mFileRecorder; + RecorderPtr mFixedBufferRecorder; std::string mFileRecorderFileName; int mShouldLogCallCounter; @@ -437,14 +437,13 @@ namespace LLError mDefaultLevel(LLError::LEVEL_DEBUG), mCrashFunction(), mTimeFunction(NULL), - mFileRecorder(NULL), - mFixedBufferRecorder(NULL), + mFileRecorder(), + mFixedBufferRecorder(), mShouldLogCallCounter(0) { } ~Settings() { - for_each(mRecorders.begin(), mRecorders.end(), DeletePointer()); mRecorders.clear(); } @@ -603,11 +602,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); @@ -635,7 +636,8 @@ namespace LLError } commonInit(dir); #if !LL_WINDOWS - addRecorder(new RecordToSyslog(identity)); + LLError::RecorderPtr recordToSyslog(new RecordToSyslog(identity)); + addRecorder(recordToSyslog); #endif } @@ -821,9 +823,9 @@ namespace LLError return mWantsFunctionName; } - void addRecorder(Recorder* recorder) + void addRecorder(RecorderPtr recorder) { - if (recorder == NULL) + if (!recorder) { return; } @@ -831,9 +833,9 @@ namespace LLError s.mRecorders.push_back(recorder); } - void removeRecorder(Recorder* recorder) + void removeRecorder(RecorderPtr recorder) { - if (recorder == NULL) + if (!recorder) { return; } @@ -850,8 +852,7 @@ namespace LLError LLError::Settings& s = LLError::Settings::get(); removeRecorder(s.mFileRecorder); - delete s.mFileRecorder; - s.mFileRecorder = NULL; + s.mFileRecorder.reset(); s.mFileRecorderFileName.clear(); if (file_name.empty()) @@ -859,16 +860,13 @@ namespace LLError return; } - RecordToFile* f = new RecordToFile(file_name); - if (!f->okay()) + RecorderPtr recordToFile(new RecordToFile(file_name)); + if (boost::dynamic_pointer_cast(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) @@ -876,16 +874,16 @@ namespace LLError LLError::Settings& s = LLError::Settings::get(); removeRecorder(s.mFixedBufferRecorder); - delete s.mFixedBufferRecorder; - s.mFixedBufferRecorder = NULL; + 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() @@ -906,7 +904,7 @@ namespace i != s.mRecorders.end(); ++i) { - LLError::Recorder* r = *i; + LLError::RecorderPtr r = *i; std::ostringstream message_stream; diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index aab695094c..681f444234 100755 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -30,6 +30,7 @@ #include "llerror.h" #include "boost/function.hpp" +#include "boost/shared_ptr.hpp" #include class LLSD; @@ -156,16 +157,14 @@ namespace LLError mWantsFunctionName; }; + typedef boost::shared_ptr 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); diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index b28c5ba4b3..6cecd6bbc8 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::RecorderPtr mRecorder; LLError::Settings* 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(mRecorder)->countMessages(); + } + + void clearMessages() + { + boost::dynamic_pointer_cast(mRecorder)->clearMessages(); + } + + void setWantsTime(bool t) + { + boost::dynamic_pointer_cast(mRecorder)->setWantsTime(t); + } + + std::string message(int n) + { + return boost::dynamic_pointer_cast(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(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(recorder)->message(0); + std::string messageWithName = boost::dynamic_pointer_cast(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(altRecorder)->countMessages(), 1); + ensure_contains("alt recorder message 0", boost::dynamic_pointer_cast(altRecorder)->message(0), "boo"); LLError::setTimeFunction(roswell); - TestRecorder* anotherRecorder(new TestRecorder); - anotherRecorder->setWantsTime(true); + LLError::RecorderPtr anotherRecorder(new TestRecorder()); + boost::dynamic_pointer_cast(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(altRecorder)->countMessages(), 2); + ensure_does_not_contain("alt recorder message 1", boost::dynamic_pointer_cast(altRecorder)->message(1), when); + ensure_equals("another recorder count", boost::dynamic_pointer_cast(anotherRecorder)->countMessages(), 1); + ensure_contains("another recorder message 0", boost::dynamic_pointer_cast(anotherRecorder)->message(0), when); + + LLError::removeRecorder(altRecorder); + LLError::removeRecorder(anotherRecorder); } } diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index 3137bd8fea..0a52844671 100755 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -38,6 +38,7 @@ #include "stringize.h" #include #include +#include #include #include #include @@ -85,68 +86,25 @@ struct WrapLLErrs 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 MessageList; MessageList mMessages; +}; + +/** + * 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(mRecorder)->messageWith(search, required); + } + + std::ostream& streamto(std::ostream& out) const + { + return boost::dynamic_pointer_cast(mRecorder)->streamto(out); + } + +private: LLError::Settings* mOldSettings; - LLError::Recorder* mProxy; + 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); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 2cb8e6a3ab..8e5d577968 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -261,7 +261,7 @@ std::string LLViewerWindow::sMovieBaseName; LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity"); -class RecordToChatConsole : public LLError::Recorder, public LLSingleton +class RecordToChatConsoleRecorder : public LLError::Recorder { public: virtual void recordMessage(LLError::ELevel level, @@ -285,6 +285,22 @@ public: } }; +class RecordToChatConsole : public LLSingleton +{ +public: + RecordToChatConsole() + : LLSingleton(), + mRecorder(new RecordToChatConsoleRecorder()) + { + } + + void startRecorder() { LLError::addRecorder(mRecorder); } + void stopRecorder() { LLError::removeRecorder(mRecorder); } + +private: + LLError::RecorderPtr mRecorder; +}; + //////////////////////////////////////////////////////////////////////////// // // LLDebugText @@ -1889,11 +1905,11 @@ void LLViewerWindow::initBase() // optionally forward warnings to chat console/chat floater // for qa runs and dev builds #if !LL_RELEASE_FOR_DOWNLOAD - LLError::addRecorder(RecordToChatConsole::getInstance()); + RecordToChatConsole::getInstance()->startRecorder(); #else if(gSavedSettings.getBOOL("QAMode")) { - LLError::addRecorder(RecordToChatConsole::getInstance()); + RecordToChatConsole::getInstance()->startRecorder(); } #endif @@ -2040,8 +2056,7 @@ void LLViewerWindow::initWorldUI() void LLViewerWindow::shutdownViews() { // clean up warning logger - LLError::removeRecorder(RecordToChatConsole::getInstance()); - + RecordToChatConsole::getInstance()->stopRecorder(); LL_INFOS() << "Warning logger is cleaned." << LL_ENDL ; delete mDebugText; diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 10f71a2843..0dd21b6a05 100755 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -95,25 +95,20 @@ public: virtual void replay(std::ostream&) {} }; -class LLReplayLogReal: public LLReplayLog, public LLError::Recorder, public boost::noncopyable +class RecordToTempFile : public LLError::Recorder, public boost::noncopyable { public: - LLReplayLogReal(LLError::ELevel level, apr_pool_t* pool): - mOldSettings(LLError::saveAndResetSettings()), - mProxy(new RecorderProxy(this)), - mTempFile("log", "", pool), // create file - mFile(mTempFile.getName().c_str()) // open it + RecordToTempFile(apr_pool_t* pPool) + : LLError::Recorder(), + boost::noncopyable(), + mTempFile("log", "", pPool), + mFile(mTempFile.getName().c_str()) { - LLError::setFatalFunction(wouldHaveCrashed); - LLError::setDefaultLevel(level); - LLError::addRecorder(mProxy); } - virtual ~LLReplayLogReal() + virtual ~RecordToTempFile() { - LLError::removeRecorder(mProxy); - delete mProxy; - LLError::restoreSettings(mOldSettings); + mFile.close(); } virtual void recordMessage(LLError::ELevel level, const std::string& message) @@ -121,13 +116,13 @@ public: mFile << message << std::endl; } - virtual void reset() + void reset() { mFile.close(); mFile.open(mTempFile.getName().c_str()); } - virtual void replay(std::ostream& out) + void replay(std::ostream& out) { mFile.close(); std::ifstream inf(mTempFile.getName().c_str()); @@ -139,12 +134,45 @@ public: } private: - LLError::Settings* mOldSettings; - LLError::Recorder* mProxy; NamedTempFile mTempFile; std::ofstream mFile; }; +class LLReplayLogReal: public LLReplayLog, public boost::noncopyable +{ +public: + LLReplayLogReal(LLError::ELevel level, apr_pool_t* pool) + : LLReplayLog(), + boost::noncopyable(), + mOldSettings(LLError::saveAndResetSettings()), + mRecorder(new RecordToTempFile(pool)) + { + LLError::setFatalFunction(wouldHaveCrashed); + LLError::setDefaultLevel(level); + LLError::addRecorder(mRecorder); + } + + virtual ~LLReplayLogReal() + { + LLError::removeRecorder(mRecorder); + LLError::restoreSettings(mOldSettings); + } + + virtual void reset() + { + boost::dynamic_pointer_cast(mRecorder)->reset(); + } + + virtual void replay(std::ostream& out) + { + boost::dynamic_pointer_cast(mRecorder)->replay(out); + } + +private: + LLError::Settings* mOldSettings; + LLError::RecorderPtr mRecorder; +}; + class LLTestCallback : public tut::callback { public: -- cgit v1.3 From 08e83a341e76de8fa4d8c4a974edbe3e0bd1c128 Mon Sep 17 00:00:00 2001 From: Stinson Linden Date: Sat, 17 May 2014 00:41:36 +0100 Subject: MAINT-4009: Final pass refactoring to eliminate memory allocation related to error reporting that is not properly cleaned up. --- indra/llcommon/llerror.cpp | 268 ++++++++++++++++++---------------- indra/llcommon/llerrorcontrol.h | 8 +- indra/llcommon/tests/llerror_test.cpp | 2 +- indra/llcommon/tests/wrapllerrs.h | 4 +- indra/test/test.cpp | 2 +- 5 files changed, 149 insertions(+), 135 deletions(-) (limited to 'indra/llcommon/tests') diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 09a2d38e1a..22cd861c72 100755 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -402,9 +402,13 @@ namespace namespace LLError { - class Settings + class SettingsConfig : public LLRefCount { + friend class Settings; + public: + virtual ~SettingsConfig(); + bool mPrintLocation; LLError::ELevel mDefaultLevel; @@ -419,80 +423,86 @@ namespace LLError LLError::TimeFunction mTimeFunction; Recorders mRecorders; - RecorderPtr mFileRecorder; - RecorderPtr mFixedBufferRecorder; + RecorderPtr mFileRecorder; + RecorderPtr mFixedBufferRecorder; std::string mFileRecorderFileName; int mShouldLogCallCounter; - static Settings& get(); + private: + SettingsConfig(); + }; + + typedef LLPointer SettingsConfigPtr; + + class Settings : public LLSingleton + { + 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(), - mFixedBufferRecorder(), - mShouldLogCallCounter(0) - { } - - ~Settings() - { - 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::getInstance()->invalidateCallSites(); - - Settings*& p = getPtr(); - delete p; - p = new Settings(); + mRecorders.clear(); + } + + Settings::Settings() + : LLSingleton(), + mSettingsConfig(new SettingsConfig()) + { + } + + SettingsConfigPtr Settings::getSettingsConfig() + { + return mSettingsConfig; } - Settings* Settings::saveAndReset() + void Settings::reset() { Globals::getInstance()->invalidateCallSites(); - - Settings*& p = getPtr(); - Settings* originalSettings = p; - p = new Settings(); - return originalSettings; + mSettingsConfig = new SettingsConfig(); } - void Settings::restore(Settings* originalSettings) + SettingsStoragePtr Settings::saveAndReset() { - Globals::getInstance()->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(pSettingsStorage.get())); + mSettingsConfig = newSettingsConfig; } } @@ -593,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); @@ -648,67 +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::getInstance()->invalidateCallSites(); - Settings& s = Settings::get(); - s.mDefaultLevel = level; + 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::getInstance()->invalidateCallSites(); - Settings& s = Settings::get(); - s.mFunctionLevelMap[function_name] = level; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mFunctionLevelMap[function_name] = level; } void setClassLevel(const std::string& class_name, ELevel level) { Globals::getInstance()->invalidateCallSites(); - Settings& s = Settings::get(); - s.mClassLevelMap[class_name] = level; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mClassLevelMap[class_name] = level; } void setFileLevel(const std::string& file_name, ELevel level) { Globals::getInstance()->invalidateCallSites(); - Settings& s = Settings::get(); - s.mFileLevelMap[file_name] = level; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mFileLevelMap[file_name] = level; } void setTagLevel(const std::string& tag_name, ELevel level) { Globals::getInstance()->invalidateCallSites(); - Settings& s = Settings::get(); - s.mTagLevelMap[tag_name] = level; + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mTagLevelMap[tag_name] = level; } LLError::ELevel decodeLevel(std::string name) @@ -753,13 +763,13 @@ namespace LLError void configure(const LLSD& config) { Globals::getInstance()->invalidateCallSites(); - Settings& s = Settings::get(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - 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"])); @@ -772,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); } } } @@ -789,10 +799,12 @@ namespace LLError mWantsLevel(true), mWantsLocation(false), mWantsFunctionName(true) - {} + { + } Recorder::~Recorder() - { } + { + } bool Recorder::wantsTime() { @@ -829,8 +841,8 @@ namespace LLError { return; } - Settings& s = Settings::get(); - s.mRecorders.push_back(recorder); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); + s->mRecorders.push_back(recorder); } void removeRecorder(RecorderPtr recorder) @@ -839,9 +851,9 @@ namespace LLError { 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()); } } @@ -849,11 +861,11 @@ namespace LLError { void logToFile(const std::string& file_name) { - LLError::Settings& s = LLError::Settings::get(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - removeRecorder(s.mFileRecorder); - s.mFileRecorder.reset(); - s.mFileRecorderFileName.clear(); + removeRecorder(s->mFileRecorder); + s->mFileRecorder.reset(); + s->mFileRecorderFileName.clear(); if (file_name.empty()) { @@ -863,18 +875,18 @@ namespace LLError RecorderPtr recordToFile(new RecordToFile(file_name)); if (boost::dynamic_pointer_cast(recordToFile)->okay()) { - s.mFileRecorderFileName = file_name; - s.mFileRecorder = recordToFile; + s->mFileRecorderFileName = file_name; + s->mFileRecorder = recordToFile; addRecorder(recordToFile); } } void logToFixedBuffer(LLLineBuffer* fixedBuffer) { - LLError::Settings& s = LLError::Settings::get(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); - removeRecorder(s.mFixedBufferRecorder); - s.mFixedBufferRecorder.reset(); + removeRecorder(s->mFixedBufferRecorder); + s->mFixedBufferRecorder.reset(); if (!fixedBuffer) { @@ -882,14 +894,14 @@ namespace LLError } RecorderPtr recordToFixedBuffer(new RecordToFixedBuffer(fixedBuffer)); - s.mFixedBufferRecorder = recordToFixedBuffer; + 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; } } @@ -898,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::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()) @@ -1042,9 +1054,9 @@ namespace LLError return false; } - 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); @@ -1058,17 +1070,17 @@ 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; @@ -1135,7 +1147,7 @@ namespace LLError } Globals* g = Globals::getInstance(); - Settings& s = Settings::get(); + SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig(); std::string message = out->str(); if (out == &g->messageStream) @@ -1158,8 +1170,8 @@ namespace LLError if (site.mPrintOnce) { - std::map::iterator messageIter = s.mUniqueLogMessages.find(message); - if (messageIter != s.mUniqueLogMessages.end()) + std::map::iterator messageIter = s->mUniqueLogMessages.find(message); + if (messageIter != s->mUniqueLogMessages.end()) { messageIter->second++; unsigned int num_messages = messageIter->second; @@ -1175,7 +1187,7 @@ namespace LLError else { message_stream << "ONCE: "; - s.mUniqueLogMessages[message] = 1; + s->mUniqueLogMessages[message] = 1; } } @@ -1183,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) @@ -1245,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 diff --git a/indra/llcommon/llerrorcontrol.h b/indra/llcommon/llerrorcontrol.h index 681f444234..56ac52e5de 100755 --- a/indra/llcommon/llerrorcontrol.h +++ b/indra/llcommon/llerrorcontrol.h @@ -29,6 +29,8 @@ #define LL_LLERRORCONTROL_H #include "llerror.h" +#include "llpointer.h" +#include "llrefcount.h" #include "boost/function.hpp" #include "boost/shared_ptr.hpp" #include @@ -181,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 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/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 6cecd6bbc8..a5aaff10c5 100755 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -86,7 +86,7 @@ namespace tut struct ErrorTestData { LLError::RecorderPtr mRecorder; - LLError::Settings* mPriorErrorSettings; + LLError::SettingsStoragePtr mPriorErrorSettings; ErrorTestData(): mRecorder(new TestRecorder()) diff --git a/indra/llcommon/tests/wrapllerrs.h b/indra/llcommon/tests/wrapllerrs.h index 0a52844671..785197ba11 100755 --- a/indra/llcommon/tests/wrapllerrs.h +++ b/indra/llcommon/tests/wrapllerrs.h @@ -82,7 +82,7 @@ struct WrapLLErrs } std::string error; - LLError::Settings* mPriorErrorSettings; + LLError::SettingsStoragePtr mPriorErrorSettings; LLError::FatalFunction mPriorFatal; }; @@ -196,7 +196,7 @@ public: } private: - LLError::Settings* mOldSettings; + LLError::SettingsStoragePtr mOldSettings; LLError::RecorderPtr mRecorder; }; diff --git a/indra/test/test.cpp b/indra/test/test.cpp index 0dd21b6a05..e42374d56b 100755 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -169,7 +169,7 @@ public: } private: - LLError::Settings* mOldSettings; + LLError::SettingsStoragePtr mOldSettings; LLError::RecorderPtr mRecorder; }; -- cgit v1.3